Использование CRUD-генератора в Symfony2

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.

Читайте также:

Docker установка и настройка

При разработке используется множество технологий. К примеру данный блог использует php(Symfony 2), mongodb, elastic, nginx это основные но также используется nodejs к примеру для минификации css, js. При разработке приходится настраивать все технологии как показано в статье. Но что делать если проектов несколько или они используют разные технологии, например другой проект использует MySQL, или еще могут использовать разные версии php или других библиотек. Для разработки и поддержки проектов на разных технологиях можно использовать Виртуальную машину и поставить на нее к примеру centos, но это не совсем удобно, надо все равно настраивать подобное окружение как на сервере и на других машинах разработчиков. Мы будет использовать контейнеры, такие как Docker. Настроем блог разработчиков чтобы использовать Docker для разработки.

Как использовать произвольное хранилище пользователей в FOSUserBundle

Практически все используют FOSUserBundle в своих Symfony проектах т.к. он ускоряет разработку и обладает хорошим набором функциональности для управления пользователями. Бандл предоставляет несколько готовых реализаций хранилищ данных: Propel и несколько для Doctrine (ORM и ODM). Это здорово, но иногда возникает необходимость работы с другими хранилищами данных. FOSUserBundle достаточно гибок и позволяет реализовать, и использовать произвольное хранилище. Для того, чтобы использовать все возможности FOSUserBundle Вам достаточно будет написать свой менеджер пользователей под конкретного провайдера.

Интеграция Paysera в Symfony

Сегодня сложно представить себе серьезный проект, где не понадобилась бы интеграция с платежными системами. Не смотря на то что существует множество популярных систем и аггрегаторов, таких как PayPal, RBKMoney, Paymentwall, Robokassa и т.д., я хочу рассказать о Paysera. Это еще одна, довольно новая платежная система. Они позиционируют себя как выгодных с точки зрения комиссий за их услуги. Paysera позволяет вашим пользователям расплачиваться карточками, SMS и т.д. Интеграция довольно простая, однако имеет некоторые неочевидные моменты, которые я и хочу осветить.

Создание сайта “Обратный отсчет” на Symfony2

Мы иногда видим сайты с обратным отсчетом, проект стартует через … Его сделать достаточно просто, и не займет много времени. Мы воспользуемся проектом fdevs/coming-soon, который основан на Symfony2. Также будем сохранять введеный пользователями адреса электронной почтой в базу данных MongoDB. У нас есть настроенное рабочее окружение Osx, о настройке можно прочитать в статье Yosemite настройка рабочего окружения. Но главное версия php не меньше 5.4. В проекте можно также использовать реляционную базу данных типа MySQL. По умолчанию в проекте вообще не используется база данных, а введеный email отправляется на почту.

Yosemite настройка рабочего окружения.

После обновления OSx Yosemite, необходимо настроить рабочую систему. Мы установим и настроим пакеты php-fpm, nginx, mongo, nodejs. Для начала установим Xcode из App Store обновим консольные команды $ xcode-select --install и уберем apache из автозагрузки $ sudo launchctl unload /System/Library/LaunchDaemons/org.apache.httpd.plist . Так как у Apple не появилось своего менеджера пакетов будем использовать проверенный brew.