Symfony вместе с DoctrineORM позволяет использовать CRUD генератор в своих приложениях.
Рассмотрим использование CRUD(Create\Read\Update\Delete) на практике. У нас уже установлена Symfony 2.5, при этом используется структура директорий версии 3.0, также создана база в Mysql.
Создадим небольшое веб приложение для добавления книг и других данных в таблицу. Итогом у нас будет возможность добавления/удаления/редактирования книги, автора, издательства в базу данных.
Создаем Bundle
$ bin/console generate:bundle --namespace=FDevs/CRUDBundle Welcome to the Symfony2 bundle generator In your code, a bundle is often referenced by its name. It can be the concatenation of all namespace parts but it's really up to you to come up with a unique name (a good practice is to start with the vendor name). Based on the namespace, we suggest FDevsCRUDBundle. Bundle name [FDevsCRUDBundle]: The bundle can be generated anywhere. The suggested default directory uses the standard conventions. Target directory [/Users/andrey/Sites/symfony/src]: Determine the format to use for the generated configuration. Configuration format (yml, xml, php, or annotation): xml To help you get started faster, the command can generate some code snippets for you. Do you want to generate the whole directory structure [no]? Summary before generation You are going to generate a "FDevs\CRUDBundle\FDevsCRUDBundle" bundle in "/Users/andrey/Sites/symfony/src/" using the "xml" format. Do you confirm generation [yes]? Bundle generation Generating the bundle code: OK Checking that the bundle is autoloaded: OK Confirm automatic update of your Kernel [yes]? Enabling the bundle inside the Kernel: OK Confirm automatic update of the Routing [yes]? Importing the bundle routing resource: OK You can now start using the generated code!
В своих приложениях использую преимущественно xml формат конфигураций.
Создаем Entity
Нам необходимо создать три Entity: Book, Author, Publisher
$ bin/console generate:doctrine:entity --entity=FDevsCRUDBundle:Book --format=xml --with-repository Welcome to the Doctrine2 entity generator This command helps you generate Doctrine2 entities. First, you need to give the entity name you want to generate. You must use the shortcut notation like AcmeBlogBundle:Post. The Entity shortcut name [FDevsCRUDBundle:Book]: Determine the format to use for the mapping information. Configuration format (yml, xml, php, or annotation) [xml]: Instead of starting with a blank entity, you can add some fields now. Note that the primary key will be added automatically (named id). Available types: array, simple_array, json_array, object, boolean, integer, smallint, bigint, string, text, datetime, datetimetz, date, time, decimal, float, blob, guid. New field name (press <return> to stop adding fields): title Field type [string]: Field length [255]: New field name (press <return> to stop adding fields): desc Name "desc" is a reserved word. New field name (press <return> to stop adding fields): description Field type [string]: text New field name (press <return> to stop adding fields): authors Field type [string]: integer New field name (press <return> to stop adding fields): publisher Field type [string]: integer New field name (press <return> to stop adding fields): publicationDate Field type [string]: date New field name (press <return> to stop adding fields): Do you want to generate an empty repository class [yes]? Summary before generation You are going to generate a "FDevsCRUDBundle:Book" Doctrine2 entity using the "xml" format. Do you confirm generation [yes]? Entity generation Generating the entity code: OK You can now start using the generated code!
При генерации нельзя указать ссылку на другую модель, это мы сделаем позже в коде.
Остальные Модели мы будем генерировать по упрощенной схеме:
$ bin/console generate:doctrine:entity --entity=FDevsCRUDBundle:Author --format=xml --with-repository --fields="fname:string(255) lname:string(255) birthday:date about:text" --no-interaction $ bin/console generate:doctrine:entity --entity=FDevsCRUDBundle:Publisher --format=xml --with-repository --fields="title:string(255) creationDate:date about:text" --no-interaction
В итоге в проекте получится такая структура
редактируем src/FDevs/CRUDBundle/Resources/config/doctrine/Book.orm.xml
для того чтобы добавить ссылку на Author и Publisher в итоге у нас получится подобное
<?xml version="1.0" encoding="utf-8"?> <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> <entity repository-class="FDevs\CRUDBundle\Entity\BookRepository" name="FDevs\CRUDBundle\Entity\Book"> <id name="id" type="integer" column="id"> <generator strategy="AUTO"/> </id> <field name="title" type="string" column="title" length="255"/> <field name="description" type="text" column="description"/> <field name="publicationDate" type="date" column="publicationDate"/> <!--меняем поле publisher на связь "many to one" с другой моделью --> <many-to-one field="publisher" target-entity="FDevs\CRUDBundle\Entity\Publisher"/> <!--меняем поле authors на связь "many to many" с другой моделью --> <many-to-many target-entity="FDevs\CRUDBundle\Entity\Author" field="authors"/> </entity> </doctrine-mapping>
- authors: у одного автора может быть много книг как и у книги может быть много авторов
- publisher: у издательства будет много книг
подробнее про связи Many To Many и подобные лучше прочитать на сайте doctrine.
Создаем таблицы в базе данных $ bin/console doctrine:schema:create
Создаем CRUD
$ bin/console doctrine:generate:crud --entity=FDevsCRUDBundle:Author --with-write Welcome to the Doctrine2 CRUD generator This command helps you generate CRUD controllers and templates. First, you need to give the entity for which you want to generate a CRUD. You can give an entity that does not exist yet and the wizard will help you defining it. You must use the shortcut notation like AcmeBlogBundle:Post. The Entity shortcut name [FDevsCRUDBundle:Author]: By default, the generator creates two actions: list and show. You can also ask it to generate "write" actions: new, update, and delete. Do you want to generate the "write" actions [yes]? Determine the format to use for the generated CRUD. Configuration format (yml, xml, php, or annotation) [annotation]: xml Determine the routes prefix (all the routes will be "mounted" under this prefix: /prefix/, /prefix/new, ...). Routes prefix [/author]: Summary before generation You are going to generate a CRUD controller for "FDevsCRUDBundle:Author" using the "xml" format. Do you confirm generation [yes]? CRUD generation Generating the CRUD code: OK Generating the Form code: OK Confirm automatic update of the Routing [yes]? Importing the CRUD routes: OK You can now start using the generated code!
при этом создается Controller, Form и View для CRUD Author. Остальные создаются аналогичным методом:
$ bin/console doctrine:generate:crud --entity=FDevsCRUDBundle:Publisher --with-write $ bin/console doctrine:generate:crud --entity=FDevsCRUDBundle:Book --with-write
за исключением того что пишет ошибку о невозможности добавить “routing resource”, но мы в любом случае будем редактировать наш файл src/FDevs/CRUDBundle/Resources/config/routing.xml
поскольку при генерации он использует routing.yml
, который в нашем случае не используется.
редактируем src/FDevs/CRUDBundle/Resources/config/routing.xml
получается такой вариант:
<?xml version="1.0" encoding="UTF-8" ?> <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> <route id="f_devs_crud_homepage" path="/"> <default key="_controller">FDevsCRUDBundle:Default:index</default> </route> <import resource="@FDevsCRUDBundle/Resources/config/routing/book.xml" prefix="/book"/> <import resource="@FDevsCRUDBundle/Resources/config/routing/author.xml" prefix="/author"/> <import resource="@FDevsCRUDBundle/Resources/config/routing/publisher.xml" prefix="/publisher"/> </routes>
мы подключили все необходимые routes, a также исправили путь по умолчанию к корню сайта.
Для того чтобы при добавлении или редактировании Книги можно было выбрать Авторов и Издание, нам необходимо внести правки в форму или модель.
Изменим src/FDevs/CRUDBundle/Form/BookType.php
->add('publisher', null, array(‘property’=>'title’))
а в src/FDevs/CRUDBundle/Entity/Author.php
добавим метод
public function __toString() { return $this->fname . ' ' . $this->lname; }
можно было использовать один из методов для обоих случаев, но для примера решил использовать оба.
На данный момент у нас уже работоспособный CRUD, и можно было бы остановиться, но мы добавим немного стиля.
Дизайн
Добавим бандл twitter/bootstrap-bundle, как его установить и использовать можно прочитать в документации.
Создадим файл меню src/FDevs/CRUDBundle/Resources/views/Default/menu.html.twig
он получится таким:
{% block menu -%} <div class="header"> <ul class="nav nav-pills pull-right"> <li><a href="{{ path('author') }}">Authors</a></li> <li><a href="{{ path('book') }}">Books</a></li> <li><a href="{{ path('publisher') }}">Publisher</a></li> </ul> <h3 class="text-muted">4devs CRUD Example</h3> </div> {% endblock %}
изменим шаблон src/FDevs/CRUDBundle/Resources/views/Default/index.html.twig
{% extends "TwitterBootstrapBundle::layout.html.twig" %} {% block container -%} {% include 'FDevsCRUDBundle:Default:menu.html.twig' %} {%- endblock %}
и action \FDevs\CRUDBundle\Controller\DefaultController::indexAction
нужно убрать $name
или присвоить ему значение по умолчанию.
Во всех остальных шаблонах CRUD заменим
{% extends '::base.html.twig' %} {% block body %}
на
{% extends "TwitterBootstrapBundle::layout.html.twig" %} {% block container -%} {% include 'FDevsCRUDBundle:Default:menu.html.twig' %}
не забываем про $ bin/console assets:install —symlink
Готово. Дальше можете сами улучшать дизайн как вам больше нравится.
Выводы
Использовать CRUD генератор в Symfony 2 очень просто, но есть отличия в использовании с другими базами данных, к примеру готового в doctrine-odm я пока не нашел. Готовый проект можно найти в репозитории 4devs.