こんにちは。
先日、酔っ払って帰宅中にメガネを紛失した武田です。
最近、Symfony2というフレームワークを利用するようになりました。
一般的な管理画面の機能であるCRUDをけっこう楽に作れるバンドルがあったので紹介してみたいと思います。
※Symfony2のドキュメントって日本語の物が少ないのでちょっとでも増やせればなんて思ってます。。。
今回はsonataAdminチュートリアルをベースに環境構築、シンブルなブログ用CRUD作成してみようと思います
実験環境
以下のバージョンで進めていきます。
- Cent OS 6.8 64bit
- PHP 7.0.13
- symfony 2.8
- MySQL 5.7.16
まずは環境構築からやっていきます。
symfonyプロジェクト作成+起動テスト
# 2.8で実験用プロジェクト作成
symfony new adminSample 2.8
cd adminSample/
# ビルドインサーバの実行
php app/console server:run 192.168.0.184:8000
※IPは環境で読み替えてください
ブラウザでアクセスしてみると。。。
無事、アクセスOK
最近のフレームワークは自前でウェブサーバまで使えて便利になりましたね
Composer インストール
今回のバンドルを入れるためにComposerを導入します。
# Composerインストール
[adjust@localhost adminSample]$ curl -sS https://getcomposer.org/installer | php
All settings correct for using Composer
Downloading...
Composer (version 1.4.1) successfully installed to: /home/adjust/sandbox/adminSample/composer.phar
Use it: php composer.phar
利用するバンドルのインストール
# sonata-project/admin-bundleインストール
php composer.phar require sonata-project/admin-bundle
Using version ^3.13 for sonata-project/admin-bundle
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
...[略]
# sonata-project/doctrine-orm-admin-bundleインストール
php composer.phar require sonata-project/doctrine-orm-admin-bundle
Using version ^3.1 for sonata-project/doctrine-orm-admin-bundle
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
...[略]
バンドルを有効化
以下に追記
vi app/AppKernel.php
$bundles = array(
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
new Symfony\Bundle\TwigBundle\TwigBundle(),
new Symfony\Bundle\MonologBundle\MonologBundle(),
new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
new AppBundle\AppBundle(),
// These are the other bundles the SonataAdminBundle relies on
[追記] new Sonata\CoreBundle\SonataCoreBundle(),
[追記] new Sonata\BlockBundle\SonataBlockBundle(),
[追記] new Knp\Bundle\MenuBundle\KnpMenuBundle(),
// And finally, the storage and SonataAdminBundle
[追記] new Sonata\DoctrineORMAdminBundle\SonataDoctrineORMAdminBundle(),
[追記] new Sonata\AdminBundle\SonataAdminBundle(),
);
configの設定
以下を追記
vi app/config/config.yml
sonata_block:
default_contexts: [cms]
blocks:
# enable the SonataAdminBundle block
sonata.admin.block.admin_list:
contexts: [admin]
以下を修正
vi app/config/config.yml
# 言語を日本語に設定
framework:
translator: { fallbacks: [jp] }
ルーティングの追加
以下を追記
vi app/config/routing.yml
admin_area:
resource: "@SonataAdminBundle/Resources/config/routing/sonata_admin.xml"
prefix: /admin
/admin以下を管理画面と設定
キャッシュのクリアとアセットのインストール
# キャッシュのクリア
php app/console cache:clear
// Clearing the cache for the dev environment with debug true
...[略]
# アセットのインストール
php app/console assets:install
Installing assets as hard copies.
--- -------------------------- ----------------
Bundle Method / Error
--- -------------------------- ----------------
? FrameworkBundle copy
? SensioDistributionBundle copy
--- -------------------------- ----------------
...[略]
ひとまずこれでsonataadminバンドル準備ではできたはず。
/admin以下にアクセスしてみましょう
とりあえずは管理画面っぽいレイアウトがでてきましたね。
まだ、肝心の管理するデータなど未設定のためメニューなどはからっぽです。
エンティティの作成
とりあえずDB周りを作らないといけませんね。
まずはエンティティを作りたいと思います。
# カテゴリテーブル用エンティティの作成
php app/console doctrine:generate:entity --entity="AppBundle:Category" --fields="name:string(255)" --no-interaction
Entity generation
created ./src/AppBundle/Entity/
created ./src/AppBundle/Entity/Category.php
> Generating entity class src/AppBundle/Entity/Category.php: OK!
> Generating repository class src/AppBundle/Repository/CategoryRepository.php: OK!
Everything is OK! Now get to work :).
# ブログ記事用エンティティの作成
php app/console doctrine:generate:entity --entity="AppBundle:BlogPost" --fields="title:string(255) body:text draft:boolean" --no-interaction
Entity generation
created ./src/AppBundle/Entity/BlogPost.php
> Generating entity class src/AppBundle/Entity/BlogPost.php: OK!
> Generating repository class src/AppBundle/Repository/BlogPostRepository.php: OK!
Everything is OK! Now get to work :).
無事エンティティが作成できました。
今回はblog_postテーブルとCategorテーブル連携させたいのでエンティティに設定を追加します。
これでblog_postとCategor間のリレーションを貼ることが出来ます。
以下を追記
vi src/AppBundle/Entity/BlogPost.php
// [略]...
/**
* @ORM\ManyToOne(targetEntity="Category", inversedBy="blogPosts")
*/
private $category;
public function setCategory(Category $category)
{
$this->category = $category;
}
public function getCategory()
{
return $this->category;
}
// [略]...
以下を修正
vi src/AppBundle/Entity/BlogPost.php
/**
* @var bool
*
* @ORM\Column(name="draft", type="boolean")
*/
[修正] private $draft = false;
vi src/AppBundle/Entity/Category.php
以下を追記
// [略]...
/**
* @ORM\OneToMany(targetEntity="BlogPost", mappedBy="category")
*/
private $blogPosts;
public function __construct()
{
$this->blogPosts = new ArrayCollection();
}
public function getBlogPosts()
{
return $this->blogPosts;
}
// [略]...
DB設定
今回はmysqlを利用します。
vi app/config/parameters.yml
以下を修正
※前もってDBは作成しておいてください
※環境にあわせて読み替えください
parameters:
database_host: 127.0.0.1
database_port: 3306
database_name: admin_sample
database_user: root
database_password: password
テーブルの作成
エンティティに定義した項目でDBにテーブルを作りましょう
# エンティティを元にDBにテーブル作成
php app/console doctrine:schema:create
eating database schema...
Database schema created successfully!
無事動いたようです。
mysqlから出来ているか確認しましょう
mysql> show tables;
+------------------------+
| Tables_in_admin_sample |
+------------------------+
| blog_post |
| category |
+------------------------+
2 rows in set (0.04 sec)
mysql> desc category;
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
+-------+--------------+------+-----+---------+----------------+
2 rows in set (0.01 sec)
mysql> desc blog_post;
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| title | varchar(255) | NO | | NULL | |
| body | longtext | NO | | NULL | |
| draft | tinyint(1) | NO | | NULL | |
| category_id | int(11) | YES | MUL | NULL | |
+-------------+--------------+------+-----+---------+----------------+
5 rows in set (0.01 sec)
mysqlにも反映されてますね!
ADMIN CLASSの作成
基本的にsonata admin bundleの各CRUDはこのadminクラスに定義する形で作ります。
まずは項目が少ないcategoryテーブルの管理画面を作りましょう。
以下を新規作成
vi src/AppBundle/Admin/CategoryAdmin.php
namespace AppBundle\Admin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Symfony\Component\Form\Extension\Core\Type\TextType;
class CategoryAdmin extends AbstractAdmin
{
// 登録,更新で利用する入力フォームの定義
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper->add('name', TextType::class);
// 第二引数は 'text'でも可能ですがsymfony3.0からは廃止されるようなので新しい書き方とします。
}
// 一覧画面での検索に利用する項目の定義
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper->add('name');
}
// 一覧画面で表示する項目の定義
protected function configureListFields(ListMapper $listMapper)
{
$listMapper->addIdentifier('name');
}
}
サービスへの登録
作成したADMIN classをサービスとして登録します。
vi config/services.yml
以下を追記
services:
# ...
admin.category:
class: AppBundle\Admin\CategoryAdmin
arguments: [~, AppBundle\Entity\Category, ~]
tags:
- { name: sonata.admin, manager_type: orm, label: Category }
ルーティングの調整
vi app/config/routing.yml
以下を追記
_sonata_admin:
resource: .
type: sonata_admin
prefix: /admin
カテゴリ管理画面確認
これでひとまずは揃ったはず動きを見てましょう
-
ダッシュボード
左メニュー及びダッシュボード中央にCategoryが追加されてることがわかります。 -
カテゴリ登録
データがないので新規登録をしてみましょう。
定義した通りカテゴリ名の項目がありますので入力してみましょう。
登録できたようです。 -
カテゴリ一覧
先に登録したカテゴリが表示されてますね。
この時点でも一般的な機能を既に備えていることが、見てもらうとわかるかなと思います。
かなり盛りだくさんで制作の際は逆に機能を削ることなるレベル
- 項目でのsort
- 検索
- 一覧で複数チェックしての削除
- json,xml,csv,xls形式での書き出し
- ページネーション
- 1ページ上での表示件数変更
ブログ記事 ADMIN CLASS
Categoryと同様にブログ記事管理画面を作成しましょう
以下を新規作成
vi src/AppBundle/Admin/BlogPostAdmin.php
namespace AppBundle\Admin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
class BlogPostAdmin extends AbstractAdmin
{
// 登録,更新で利用する入力フォームの定義
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('title', TextType::class)
->add('body', TextareaType::class)
// カテゴリに関してはリレーションをはったcategoryテーブルから参照させます。
->add('category', EntityType::class, array(
'class' => 'AppBundle\Entity\Category',
'property' => 'name',
))
;
}
// 一覧画面での検索に利用する項目の定義
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('title')
// こちらもカテゴリに関しては~
->add('category', null, array(), EntityType::class, array(
'class' => 'AppBundle\Entity\Category',
'choice_label' => 'name',
))
->add('draft')
;
}
// 一覧画面で表示する項目の定義
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('title')
->add('category.name') // こちらもカテゴリに関しては~
->add('draft')
;
}
}
- カテゴリテーブルとのリレーションがあるので若干書き方が違います。
サービスへの追加
vi app/config/services.yml
以下を追記
services:
# ...
admin.blog_post:
class: AppBundle\Admin\BlogPostAdmin
arguments: [~, AppBundle\Entity\BlogPost, ~]
tags:
- { name: sonata.admin, manager_type: orm, label: Blog post }
ブログ記事管理画面確認
設定が終わったので実際触ってみましょう
-
登録画面
設定通り、項目が表示なされました。
記事も無事登録できるようです。
-
一覧画面
まとめ
- いかがでしょうか。シンプルな管理画面ならこの程度の行程で実装可能です。
どうです使ってみたくなってきたんじゃあないでしょうか?
次回はこれを改修してよりよいものにしていく予定です。
以下の機能を追加を考えてます。- 日本語化
- バリデーション
- 画像の登録
- etc
コメントを残す