Introduction
In this chapter, we'll step by step to create a simple blog system, that helps you understand how to use phoenix.
Create Admin Package
First, we have to create a basic blog admin package. please type this command:
php bin/console muse init Blog/Admin category.categories
php bin/console muse add-subsystem Blog/Admin article.articles
php bin/console muse add-subsystem Blog/Admin comment.comments
After package created, register package and add assets link.
// src/Windwalker/Windwalker.php
class Windwalker extends \Windwalker\Core\Windwalker
{
public static function loadPackages()
{
return array(
'system' => new SystemPackage,
'phoenix' => new PhoenixPackage,
'admin' => new \Blog\Admin\AdminPackage,
);
}
// ...
$ php bin/console asset sync admin
And add routing to /etc/routing.yml
.
# /etc/routing.yml
# ...
admin:
pattern: /admin
package: admin
Migration
Open src/Blog/Admin/*.php
files, change migration like below:
// src/Blog/Admin/xxxxxxxxxxxxxx_CategoryInit.php
// ...
class CategoryInit extends AbstractMigration
{
public function up()
{
$this->db->getTable(Table::CATEGORIES, true)
->addColumn(new Column\Primary('id'))
->addColumn(new Column\Varchar('title'))
->addColumn(new Column\Varchar('alias'))
->addColumn(new Column\Datetime('created'))
->addColumn(new Column\Integer('created_by'))
->addColumn(new Column\Datetime('modified'))
->addColumn(new Column\Integer('modified_by'))
->addColumn(new Column\Integer('ordering'))
->addColumn(new Column\Tinyint('state'))
->addColumn(new Column\Char('language', 7))
->addColumn(new Column\Text('params'))
->addIndex(Key::TYPE_INDEX, 'idx_categories_alias', 'alias')
->addIndex(Key::TYPE_INDEX, 'idx_categories_alias', 'language')
->addIndex(Key::TYPE_INDEX, 'idx_categories_created_by', 'created_by')
->create(true);
}
public function down()
{
$this->db->getTable(Table::CATEGORIES, true)->drop(true);
}
}
// src/Blog/Admin/xxxxxxxxxxxxxx_ArticleInit.php
class ArticleInit extends AbstractMigration
{
public function up()
{
$this->db->getTable(Table::ARTICLES, true)
->addColumn(new Column\Primary('id'))
->addColumn(new Column\Integer('category_id'))
->addColumn(new Column\Varchar('title'))
->addColumn(new Column\Varchar('alias'))
->addColumn(new Column\Text('introtext'))
->addColumn(new Column\Text('fulltext'))
->addColumn(new Column\Integer('version'))
->addColumn(new Column\Datetime('created'))
->addColumn(new Column\Integer('created_by'))
->addColumn(new Column\Datetime('modified'))
->addColumn(new Column\Integer('modified_by'))
->addColumn(new Column\Integer('ordering'))
->addColumn(new Column\Tinyint('state'))
->addColumn(new Column\Char('language', 7))
->addColumn(new Column\Text('params'))
->addIndex(Key::TYPE_INDEX, 'idx_articles_alias', 'alias')
->addIndex(Key::TYPE_INDEX, 'idx_articles_alias', 'language')
->addIndex(Key::TYPE_INDEX, 'idx_articles_created_by', 'created_by')
->addIndex(Key::TYPE_INDEX, 'idx_articles_category_id', 'category_id')
->create(true);
}
public function down()
{
$this->db->getTable(Table::ARTICLES, true)->drop(true);
}
}
// src/Blog/Admin/xxxxxxxxxxxxxx_CommentInit.php
class CommentInit extends AbstractMigration
{
public function up()
{
$this->db->getTable(Table::COMMENTS, true)
->addColumn(new Column\Primary('id'))
->addColumn(new Column\Integer('article_id'))
->addColumn(new Column\Varchar('name'))
->addColumn(new Column\Varchar('email'))
->addColumn(new Column\Text('text'))
->addColumn(new Column\Datetime('created'))
->addColumn(new Column\Integer('ordering'))
->addColumn(new Column\Tinyint('state'))
->addColumn(new Column\Text('params'))
->addIndex(Key::TYPE_INDEX, 'idx_comments_article_id', 'article_id')
->create(true);
}
public function down()
{
$this->db->getTable(Table::COMMENTS, true)->drop(true);
}
}
Run migration:
php bin/console migration migrate -p=admin
Now you can open http://{your_site}/admin/categories
to see your admin page.
Fake Data
We must add some fake data to help us developing. Use seeder to do this work, please modify src/Blog/Admin/Seed/*.php
files.
First check that the seeder ordering is CategorySeeder
-> ArticleSeeder
-> CommentSeeder
in DatabaseSeeder
.
// src/Blog/Admin/DatabaseSeeder.php
// ...
class DatabaseSeeder extends AbstractSeeder
{
/**
* doExecute
*
* @return void
*/
public function doExecute()
{
$this->execute(new CategorySeeder);
$this->execute(new ArticleSeeder);
$this->execute(new CommentSeeder);
// @muse-placeholder seeder-execute Do not remove this.
}
// ...
Then add modify all other seeder class to:
// src/Blog/Admin/Seed/CategorySeeder.php
// ...
class CategorySeeder extends AbstractSeeder
{
public function doExecute()
{
$faker = Factory::create();
$mapper = new CategoryMapper;
foreach (range(1, 7) as $i)
{
$data = new Data;
$data['title'] = $faker->word;
$data['alias'] = OutputFilter::stringURLSafe($data['title']);
$data['version'] = rand(1, 50);
$data['created'] = $faker->dateTime->format(DateTime::FORMAT_SQL);
$data['created_by'] = rand(20, 100);
$data['modified'] = $faker->dateTime->format(DateTime::FORMAT_SQL);
$data['modified_by'] = rand(20, 100);
$data['ordering'] = $i;
$data['state'] = $faker->randomElement(array(1, 1, 1, 1, 0, 0));
$data['language'] = 'en-GB';
$data['params'] = '';
$mapper->createOne($data);
$this->command->out('.', false);
}
$this->command->out();
}
public function doClean()
{
$this->db->getTable(Table::CATEGORIES)->truncate();
}
}
// src/Blog/Admin/Seed/ArticleSeeder.php
// ...
class ArticleSeeder extends AbstractSeeder
{
public function doExecute()
{
$faker = Factory::create();
$categories = with(new CategoryMapper)->findAll();
$mapper = new ArticleMapper;
foreach ($categories as $category)
{
foreach (range(1, rand(3, 5)) as $i)
{
$data = new Data;
$data['title'] = $faker->sentence(rand(3, 5));
$data['alias'] = OutputFilter::stringURLSafe($data['title']);
$data['category_id'] = $category->id;
$data['introtext'] = $faker->paragraph(5);
$data['fulltext'] = $faker->paragraph(5);
$data['version'] = rand(1, 50);
$data['created'] = $faker->dateTime->format(DateTime::FORMAT_SQL);
$data['created_by'] = rand(20, 100);
$data['modified'] = $faker->dateTime->format(DateTime::FORMAT_SQL);
$data['modified_by'] = rand(20, 100);
$data['ordering'] = $i;
$data['state'] = $faker->randomElement(array(1, 1, 1, 1, 0, 0));
$data['language'] = 'en-GB';
$data['params'] = '';
$mapper->createOne($data);
$this->command->out('.', false);
}
}
$this->command->out();
}
public function doClean()
{
$this->db->getTable(Table::ARTICLES)->truncate();
}
}
// src/Blog/Admin/Seed/CommentSeeder.php
// ...
class CommentSeeder extends AbstractSeeder
{
public function doExecute()
{
$faker = Factory::create();
$articles = with(new ArticleMapper)->findAll();
$mapper = new CommentMapper;
foreach ($articles as $article)
{
foreach (range(1, rand(1, 7)) as $i)
{
$data = new Data;
$data['article_id'] = $article->id;
$data['name'] = $faker->name;
$data['email'] = $faker->email;
$data['text'] = $faker->paragraph(5);
$data['created'] = $faker->dateTime->format(DateTime::FORMAT_SQL);
$data['ordering'] = $i;
$data['state'] = $faker->randomElement(array(1, 1, 1, 1, 0, 0));
$data['params'] = '';
$mapper->createOne($data);
$this->command->out('.', false);
}
}
$this->command->out();
}
public function doClean()
{
$this->db->getTable(Table::COMMENTS)->truncate();
}
}
Run seeder import
$ php bin/console seed import -p=admin
If migration and seeder works fine, open the admin page, you will see sample data to test.
The first Categories
menu item is a placeholder, you can delete it in src/Blog/Admin/Templates/_global/admin/submenu.blade.php
.
Found a typo? Help us improve this document.
This document is for Windwalker Joomla RAD, if you are finding Windwalker PHP framework, please see: Windwalker Framework