Skip to content

管理者用のバックエンドをセットアップする

データベースに次のカンファレンスを追加するのは、プロジェクトの管理者の仕事です。 管理者用のバックエンド は、Webサイトの保護された場所となり、そこで プロジェクト管理者 は、Webサイトのデータを管理したり、フィードバックをモデレートしたりできます。

早く作成するのにどうしましょうか?プロジェクトのモデルに基づく管理者用のバックエンドを生成することができる EasyAdmin バンドルを使いましょう。

更に依存パッケージをインストールする

webapp パッケージはたくさんの便利なパッケージを追加しますが、より特殊な機能を使うためには更に依存を追加しなければなりません。どうやって依存を追加するのでしょうか? Composerを使います。"普通" のComposerパッケージの他に、2種類の "特別" なパッケージを使います:

  • Symfony Components: コア機能とほとんどのアプリケーションで必要な低レベルの抽象(ルーティング、コンソール、HTTPクライアント、メーラー、キャッシュ...)を実装したパッケージ。
  • Symfony Bundles: 高レベル機能を追加したり、サードパーティライブラリを統合するパッケージ(ほとんどのバンドルはコミュニティによって開発されています)。

EasyAdmin をプロジェクトの依存に追加しましょう:

1
$ symfony composer req "easycorp/easyadmin-bundle:4.x-dev"

admineasycorp/easyadmin-bundle パッケージのエイリアスです。

エイリアス はComposerの機能ではありませんが、Symfonyが提供している便利な概念です。エイリアスはポピュラーなComposerパッケージのショートカットです。アプリケーションでORMを使いたいですか? orm を追加してください。APIを開発したいですか? api を追加してください。エイリアスは自動的に1つ以上の通常のComposerパッケージとして解決されます。エイリアスは、Symfonyコアチームによって作成されています。

もう一つの便利な機能として、いつでも symfony ベンダープリフィクスを省略することができます。 symfony/cache の代わりに cache を追加してください。

Tip

symfony/flex というComposerプラグインについて説明したのを覚えているでしょうか?エイリアスは flex の機能の一つです。

EasyAdmin を設定する

EasyAdminは特別なコントローラーによって、アプリケーションの管理者画面を自動的に作成します。

EasyAdminを使い始めるにあたって、Webサイトのデータを管理するメインの入口になる "管理者ダッシュボード" を作りましょう。

1
$ symfony console make:admin:dashboard

デフォルトの答えをそのまま選んでいくと次のようなコントローラーができます:

src/Controller/Admin/DashboardController.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
namespace App\Controller\Admin;

use EasyCorp\Bundle\EasyAdminBundle\Config\Dashboard;
use EasyCorp\Bundle\EasyAdminBundle\Config\MenuItem;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractDashboardController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;

class DashboardController extends AbstractDashboardController
{
    /**
     * @Route("/admin", name="admin")
     */
    public function index(): Response
    {
        return parent::index();
    }

    public function configureDashboard(): Dashboard
    {
        return Dashboard::new()
            ->setTitle('Guestbook');
    }

    public function configureMenuItems(): iterable
    {
        yield MenuItem::linkToDashboard('Dashboard', 'fa fa-home');
        // yield MenuItem::linkToCrud('The Label', 'icon class', EntityClass::class);
    }
}

慣例により全ての管理者用コントローラーは App\Controller\Admin というネームスペースに保存されます。

生成された管理者用バックエンドには、 index() メソッドに対して設定した /admin からアクセスできます。このURLは何でも好きなものに変更することができます:

/admin

ドーン! 素敵な見た目の管理者インターフェースができました。しかも必要に応じてカスタマイズできます。

次のステップでは、カンファレンスとコメントを管理するためのコントローラーを作ります。

ダッシュボードのコントローラの中に、"CRUDs" へのリンクを追加するというコメントが入った configureMenuItem() メソッドがあることに気づいたかもしれません。 CRUD は "Create, Read, Update, Delete" (作成、参照、更新、削除)の頭文字を取った略語で、エンティティに対して行う4つの基本的な操作です。この4つはまさに管理者画面でやりたいことです。EasyAdminでは検索と絞り込みもできるので、次のレベルまで対応しています。

カンファレンスのためのCRUDを作ってみます:

1
$ symfony console make:admin:crud

カンファレンスの管理者画面を作るために 1 を選び、残りの質問にはデフォルトの答えを選んでください。次のようなファイルが作成されます:

src/Controller/Admin/ConferenceCrudController.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
namespace App\Controller\Admin;

use App\Entity\Conference;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;

class ConferenceCrudController extends AbstractCrudController
{
    public static function getEntityFqcn(): string
    {
        return Conference::class;
    }

    /*
    public function configureFields(string $pageName): iterable
    {
        return [
            IdField::new('id'),
            TextField::new('title'),
            TextEditorField::new('description'),
        ];
    }
    */
}

コメントについても同じことをします:

1
$ symfony console make:admin:crud

最後のステップでは、カンファレンスとコメントの管理者用CRUD画面をダッシュボードにリンクします:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
--- a/src/Controller/Admin/DashboardController.php
+++ b/src/Controller/Admin/DashboardController.php
@@ -2,6 +2,8 @@

 namespace App\Controller\Admin;

+use App\Entity\Comment;
+use App\Entity\Conference;
 use EasyCorp\Bundle\EasyAdminBundle\Config\Dashboard;
 use EasyCorp\Bundle\EasyAdminBundle\Config\MenuItem;
 use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractDashboardController;
@@ -40,7 +42,8 @@ class DashboardController extends AbstractDashboardController

     public function configureMenuItems(): iterable
     {
-        yield MenuItem::linkToDashboard('Dashboard', 'fa fa-home');
-        // yield MenuItem::linkToCrud('The Label', 'fas fa-list', EntityClass::class);
+        yield MenuItem::linktoRoute('Back to the website', 'fas fa-home', 'homepage');
+        yield MenuItem::linkToCrud('Conferences', 'fas fa-map-marker-alt', Conference::class);
+        yield MenuItem::linkToCrud('Comments', 'fas fa-comments', Comment::class);
     }
 }

configureMenuItems() メソッドを上書きして、関連するアイコンつきのメニューを追加し、更にWebサイトのトップページに戻るリンクも追加しました。

EasyAdminでは MenuItem::linkToRoute() メソッドにより、エンティティのCRUDに簡単にリンクするAPIを公開しています。

メインのダッシュボードページは現時点では空っぽです。ダッシュボードは、様々な統計や関連情報を表示することができる場所です。ダッシュボードに表示したい重要事項は特にないので、カンファレンス一覧にリダイレクトすることにしましょう。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
--- a/src/Controller/Admin/DashboardController.php
+++ b/src/Controller/Admin/DashboardController.php
@@ -7,6 +7,7 @@ use App\Entity\Conference;
 use EasyCorp\Bundle\EasyAdminBundle\Config\Dashboard;
 use EasyCorp\Bundle\EasyAdminBundle\Config\MenuItem;
 use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractDashboardController;
+use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
 use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\Routing\Annotation\Route;

@@ -15,7 +16,10 @@ class DashboardController extends AbstractDashboardController
     #[Route('/admin', name: 'admin')]
     public function index(): Response
     {
-        return parent::index();
+        $routeBuilder = $this->container->get(AdminUrlGenerator::class);
+        $url = $routeBuilder->setController(ConferenceCrudController::class)->generateUrl();
+
+        return $this->redirect($url);

         // Option 1. You can make your dashboard redirect to some common page of your backend
         //

エンティティのリレーション(コメントと紐づくカンファレンス)を表示するとき、EasyAdminはカンファレンスの文字列としての表現を使おうとします。エンティティに __toString() マジックメソッドが定義されていなければ、デフォルトとしてエンティティの名前と主キーを利用します( Conference #1 のように)。リレーションの表示をより意味のあるものにするためには、 Conference クラスにメソッドを追加しましょう:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
--- a/src/Entity/Conference.php
+++ b/src/Entity/Conference.php
@@ -35,6 +35,11 @@ class Conference
         $this->comments = new ArrayCollection();
     }

+    public function __toString(): string
+    {
+        return $this->city.' '.$this->year;
+    }
+
     public function getId(): ?int
     {
         return $this->id;

これで、管理者用バックエンドからカンファレンスを直接追加/変更/削除することができるようになりました。一つ以上カンファレンスを作成して遊んでみましょう。

/admin

EasyAdmin をカスタマイズする

デフォルトの管理者用のバックエンドが正しく動くようになりましたが、カスタマイズしてさらに改善することができます。コメントのエンティティに簡単な修正をして、どんなことができるか見てみましょう:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
--- a/src/Controller/Admin/CommentCrudController.php
+++ b/src/Controller/Admin/CommentCrudController.php
@@ -3,10 +3,17 @@
 namespace App\Controller\Admin;

 use App\Entity\Comment;
+use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
+use EasyCorp\Bundle\EasyAdminBundle\Config\Filters;
 use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
+use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
+use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
+use EasyCorp\Bundle\EasyAdminBundle\Field\EmailField;
 use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
+use EasyCorp\Bundle\EasyAdminBundle\Field\TextareaField;
 use EasyCorp\Bundle\EasyAdminBundle\Field\TextEditorField;
 use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
+use EasyCorp\Bundle\EasyAdminBundle\Filter\EntityFilter;

 class CommentCrudController extends AbstractCrudController
 {
@@ -15,14 +22,43 @@ class CommentCrudController extends AbstractCrudController
         return Comment::class;
     }

-    /*
+    public function configureCrud(Crud $crud): Crud
+    {
+        return $crud
+            ->setEntityLabelInSingular('Conference Comment')
+            ->setEntityLabelInPlural('Conference Comments')
+            ->setSearchFields(['author', 'text', 'email'])
+            ->setDefaultSort(['createdAt' => 'DESC'])
+        ;
+    }
+
+    public function configureFilters(Filters $filters): Filters
+    {
+        return $filters
+            ->add(EntityFilter::new('conference'))
+        ;
+    }
+
     public function configureFields(string $pageName): iterable
     {
-        return [
-            IdField::new('id'),
-            TextField::new('title'),
-            TextEditorField::new('description'),
-        ];
+        yield AssociationField::new('conference');
+        yield TextField::new('author');
+        yield EmailField::new('email');
+        yield TextareaField::new('text')
+            ->hideOnIndex()
+        ;
+        yield TextField::new('photoFilename')
+            ->onlyOnIndex()
+        ;
+
+        $createdAt = DateTimeField::new('createdAt')->setFormTypeOptions([
+            'years' => range(date('Y'), date('Y') + 5),
+            'widget' => 'single_text',
+        ]);
+        if (Crud::PAGE_EDIT === $pageName) {
+            yield $createdAt->setFormTypeOption('disabled', true);
+        } else {
+            yield $createdAt;
+        }
     }
-    */
 }

Comment 画面をカスタマイズするために、 configureFields() メソッドで明示的に項目名を列挙すると、思い通りの順番で項目を並べることができます。項目ごとにより詳細に設定することもできます。たとえば、一覧画面ではテキスト項目を隠すことができます。

写真なしのコメントを追加しましょう。ここでは日付は手動でセットしましょう; 後のステップで createdAt カラムを自動的にセットするようにします。

/admin?crudAction=index&crudId=2bfa220&menuIndex=2&submenuIndex=-1

configureFilters() メソッドでは、検索画面にどんな絞り込み項目を表示するかを定義することができます。

/admin?crudAction=index&crudId=2bfa220&menuIndex=2&submenuIndex=-1

これらのカスタマイズで、EasyAdmin を使って可能なことを少し紹介をしました。

カンファレンスでコメントをフィルターしたり、メールアドレスでコメントを検索したりして、管理者画面を遊んでみてください。問題が一つあるとすれば、誰もがバックエンドにアクセスできるようになっていることですが、後のステップでセキュアにしていきますので、心配しないでください。

1
$ symfony run psql -c "TRUNCATE conference RESTART IDENTITY CASCADE"
This work, including the code samples, is licensed under a Creative Commons BY-NC-SA 4.0 license.
TOC
    Version