跳到内容

表单视图

编辑此页

上一章节中,你已经看到了冰山一角。但是还有很多东西值得探索!在接下来的章节中,你将为更复杂的 BlogPost 模型创建一个 Admin 类。同时,你将学习如何使事情变得更漂亮一些。

引导 Admin 类

基本类定义将与 CategoryAdmin 相同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// src/Admin/BlogPostAdmin.php

namespace App\Admin;

use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;

final class BlogPostAdmin extends AbstractAdmin
{
    protected function configureFormFields(FormMapper $form): void
    {
        // ... configure $form
    }

    protected function configureListFields(ListMapper $list): void
    {
        // ... configure $list
    }
}

服务定义也同样适用

1
2
3
4
5
6
7
# config/services.yaml

services:
    admin.blog_post:
        class: App\Admin\BlogPostAdmin
        tags:
            - { name: sonata.admin, model_class: App\Entity\BlogPost, manager_type: orm, label: 'Blog post' }

配置 FormMapper

如果你已经了解 Symfony 表单组件,那么 FormMapper 看起来会非常相似。

你使用 add() 方法将字段添加到表单中。第一个参数是字段值映射到的属性名称,第二个参数是字段的类型(请参阅 字段类型参考),第三个参数是用于自定义表单类型的其他选项。只有第一个参数是必需的,因为表单组件具有类型猜测器来猜测类型。

BlogPost 模型有 4 个属性:idtitlebodycategoryid 属性的值由数据库自动生成。这意味着表单视图需要 3 个字段:title、body 和 category。

title 和 body 字段是 TextTypeTextareaType 字段,你可以直接添加它们

1
2
3
4
5
6
7
8
9
10
11
12
// src/Admin/BlogPostAdmin.php

use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;

protected function configureFormFields(FormMapper $form): void
{
    $form
        ->add('title', TextType::class)
        ->add('body', TextareaType::class)
    ;
}

但是,category 字段将引用另一个模型。你如何解决这个问题呢?

添加引用其他模型的字段

使用实体类型

关于如何添加引用其他模型的字段,你有几种不同的选择。最基本的选择是使用 Doctrine Bridge 提供的 EntityType。这将渲染一个选择字段,并将可用的实体作为选项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// src/Admin/BlogPostAdmin.php

use App\Entity\Category;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;

protected function configureFormFields(FormMapper $form): void
{
    $form
        // ...
        ->add('category', EntityType::class, [
            'class' => Category::class,
            'choice_label' => 'name',
        ])
    ;
}

由于每篇博客文章只有一个类别,因此它呈现为选择列表

Sonata EntityType

当管理员想要创建一个新类别时,他们需要转到类别管理页面并创建一个新类别。

使用 Sonata 模型类型

为了让管理员的生活更轻松,你可以使用 ModelType 字段。此字段类型也将呈现为选择字段,但它包含一个创建按钮,用于打开一个对话框,其中包含被引用模型的管理员界面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// src/Admin/BlogPostAdmin.php

use App\Entity\Category;
use Sonata\AdminBundle\Form\Type\ModelType;

protected function configureFormFields(FormMapper $form): void
{
    $form
        ->add('category', ModelType::class, [
            'class' => Category::class,
            'property' => 'name',
        ])
    ;
}
Sonata ModelType

使用分组和标签页

使用分组

目前,所有内容都放在一个块中。由于表单只有三个字段,因此仍然可用,但它很快就会变得非常混乱。为了解决这个问题,form mapper 还支持将字段分组在一起。

例如,title 和 body 字段可以属于 Content 组,而 category 字段可以属于 Meta data 组。为此,请使用 with() 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// src/Admin/BlogPostAdmin.php

use App\Entity\Category;
use Sonata\AdminBundle\Form\Type\ModelType
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;

protected function configureFormFields(FormMapper $form): void
{
    $form
        ->with('Content')
            ->add('title', TextType::class)
            ->add('body', TextareaType::class)
        ->end()
        ->with('Meta data')
            ->add('category', ModelType::class, [
                'class' => Category::class,
                'property' => 'name',
            ])
        ->end()
    ;
}

第一个参数是组的名称/标签,第二个参数是选项数组。例如,你可以将 HTML 类传递给组以调整样式

1
2
3
4
5
6
7
8
9
10
11
12
13
// src/Admin/BlogPostAdmin.php

protected function configureFormFields(FormMapper $form): void
{
    $form
        ->with('Content', ['class' => 'col-md-9'])
            // ...
        ->end()
        ->with('Meta data', ['class' => 'col-md-3'])
            // ...
        ->end()
    ;
}

这将产生一个更漂亮的编辑页面

Sonata edit page

使用标签页

如果你有更多的选项,你还可以使用多个标签页,使用 tab() 快捷方法

1
2
3
4
5
6
7
8
9
10
11
12
$form
    ->tab('Post')
        ->with('Content', ...)
            // ...
        ->end()
        // ...
    ->end()

    ->tab('Publish Options')
        // ...
    ->end()
;

创建一个博客文章

你现在已经完成了 BlogPost 模型的漂亮的表单视图。现在是时候通过创建一个帖子来测试它了。

按下 “创建” 按钮后,你可能会看到一条绿色消息,例如:项目 “AppEntityBlogPost:00000000192ba93c000000001b786396” 已成功创建。

虽然 SonataAdminBundle 非常友好地通知管理员创建成功,但类名和某种哈希值并不是很友好。这是 SonataAdminBundle 中对象的默认字符串表示形式。你可以通过在 Admin 类中定义 toString() 方法来更改它。这将接收要转换为字符串的对象作为第一个参数

1
2
3
4
5
6
7
8
9
10
11
12
13
// src/Admin/BlogPostAdmin.php

use App\Entity\BlogPost;

final class BlogPostAdmin extends AbstractAdmin
{
    public function toString(object $object): string
    {
        return $object instanceof BlogPost
            ? $object->getTitle()
            : 'Blog Post'; // shown in the breadcrumb on the create view
    }
}

注意

没有下划线前缀!toString() 是正确的!

总结

在本教程中,你首次接触了 SonataAdminBundle 最强大的功能:能够自定义所有内容。你从创建一个表单开始,最终为你的管理员创建了一个漂亮的编辑页面。

下一章节中,你将了解列表和数据网格操作。

这项工作,包括代码示例,根据 Creative Commons BY-SA 3.0 许可协议获得许可。
目录
    版本