123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- Architecture
- ============
- The architecture of the ``SonataAdminBundle`` is primarily inspired by the Django Admin
- Project, which is truly a great project. More information can be found at the
- `Django Project Website`_.
- If you followed the instructions on the :doc:`getting_started` page, you should by
- now have an ``Admin`` class and an ``Admin`` service. In this chapter, we'll discuss more in
- depth how it works.
- The Admin Class
- ---------------
- The ``Admin`` class maps a specific model to the rich CRUD interface provided by
- ``SonataAdminBundle``. In other words, using your ``Admin`` classes, you can configure
- what is shown by ``SonataAdminBundle`` in each CRUD action for the associated model.
- By now you've seen 3 of those actions in the ``getting started`` page: list,
- filter and form (for creation/editing). However, a fully configured ``Admin`` class
- can define more actions:
- * ``list``: The fields displayed in the list table
- * ``filter``: The fields available for filtering the list
- * ``form``: The fields used to create/edit the entity
- * ``show``: The fields used to show the entity
- * Batch actions: Actions that can be performed on a group of entities
- (e.g. bulk delete)
- The ``Sonata\AdminBundle\Admin\Admin`` class is provided as an easy way to
- map your models, by extending it. However, any implementation of the
- ``Sonata\AdminBundle\Admin\AdminInterface`` can be used to define an ``Admin``
- service. For each ``Admin`` service, the following required dependencies are
- automatically injected by the bundle:
- * ``ConfigurationPool``: configuration pool where all Admin class instances are stored
- * ``ModelManager``: service which handles specific code relating to your persistence layer (e.g. Doctrine ORM)
- * ``FormContractor``: builds the forms for the edit/create views using the Symfony ``FormBuilder``
- * ``ShowBuilder``: builds the show fields
- * ``ListBuilder``: builds the list fields
- * ``DatagridBuilder``: builds the filter fields
- * ``Request``: the http request received
- * ``RouteBuilder``: allows you to add routes for new actions and remove routes for default actions
- * ``RouterGenerator``: generates the different urls
- * ``SecurityHandler``: handles permissions for model instances and actions
- * ``Validator``: handles model validation
- * ``Translator``: generates translations
- * ``LabelTranslatorStrategy``: a strategy to use when generating labels
- * ``MenuFactory``: generates the side menu, depending on the current action
- .. note::
- Each of these dependencies is used for a specific task, briefly described above.
- If you wish to learn more about how they are used, check the respective documentation
- chapter. In most cases, you won't need to worry about their underlying implementation.
- All of these dependencies have default values that you can override when declaring any of
- your ``Admin`` services. This is done using a ``call`` to the matching "setter":
- .. configuration-block::
- .. code-block:: xml
- <service id="sonata.admin.post" class="Acme\DemoBundle\Admin\PostAdmin">
- <tag name="sonata.admin" manager_type="orm" group="Content" label="Post"/>
- <argument />
- <argument>Acme\DemoBundle\Entity\Post</argument>
- <argument />
- <call method="setLabelTranslatorStrategy">
- <argument>sonata.admin.label.strategy.underscore</argument>
- </call>
- </service>
- .. code-block:: yaml
- services:
- sonata.admin.post:
- class: Acme\DemoBundle\Admin\PostAdmin
- tags:
- - { name: sonata.admin, manager_type: orm, group: "Content", label: "Post" }
- arguments:
- - ~
- - Acme\DemoBundle\Entity\Post
- - ~
- calls:
- - [ setLabelTranslatorStrategy, [sonata.admin.label.strategy.underscore]]
- Here, we declare the same ``Admin`` service as in the :doc:`getting_started` chapter, but using a
- different label translator strategy, replacing the default one. Notice that
- ``sonata.admin.label.strategy.underscore`` is a service provided by ``SonataAdminBundle``,
- but you could just as easily use a service of your own.
- CRUDController
- --------------
- The ``CRUDController`` contains the actions you have available to manipulate
- your model instances, like create, list, edit or delete. It uses the ``Admin``
- class to determine its behavior, like which fields to display in the edit form,
- or how to build the list view. Inside the ``CRUDController``, you can access the
- ``Admin`` class instance via the ``$admin`` variable.
- .. note::
- `CRUD is an acronym`_ for "Create, Read, Update and Delete"
- The ``CRUDController`` is no different to any other Symfony2 controller, meaning
- that you have all the usual options available to you, like getting services from
- the Dependency Injection Container (DIC).
- This is particularly useful if you decide to extend the ``CRUDController`` to
- add new actions or change the behavior of existing ones. You can specify which controller
- to use when declaring the ``Admin`` service by passing it as the 3rd argument. For example
- to set the controller to ``AcmeDemoBundle:PostAdmin``:
- .. configuration-block::
- .. code-block:: xml
- <services>
- <service id="sonata.admin.post" class="Acme\DemoBundle\Admin\PostAdmin">
- <tag name="sonata.admin" manager_type="orm" group="Content" label="Post"/>
- <argument />
- <argument>Acme\DemoBundle\Entity\Post</argument>
- <argument>AcmeDemoBundle:PostAdmin</argument>
- <call method="setTranslationDomain">
- <argument>AcmeDemoBundle</argument>
- </call>
- </service>
- </services>
- .. code-block:: yaml
- services:
- sonata.admin.post:
- class: Acme\DemoBundle\Admin\PostAdmin
- tags:
- - { name: sonata.admin, manager_type: orm, group: "Content", label: "Post" }
- arguments:
- - ~
- - Acme\DemoBundle\Entity\Post
- - AcmeDemoBundle:PostAdmin
- calls:
- - [ setTranslationDomain, [AcmeDemoBundle]]
- When extending ``CRUDController``, remember that the ``Admin`` class already has
- a set of automatically injected dependencies that are useful when implementing several
- scenarios. Refer to the existing ``CRUDController`` actions for examples of how to get
- the best out of them.
- Fields Definition
- -----------------
- Your ``Admin`` class defines which of your model's fields will be available in each
- action defined in your ``CRUDController``. So, for each action, a list of field mappings
- is generated. These lists are implemented using the ``FieldDescriptionCollection`` class
- which stores instances of ``FieldDescriptionInterface``. Picking up on our previous
- ``PostAdmin`` class example:
- .. code-block:: php
- namespace Acme\DemoBundle\Admin;
- use Sonata\AdminBundle\Admin\Admin;
- use Sonata\AdminBundle\Datagrid\ListMapper;
- use Sonata\AdminBundle\Datagrid\DatagridMapper;
- use Sonata\AdminBundle\Form\FormMapper;
- class PostAdmin extends Admin
- {
- // Fields to be shown on create/edit forms
- protected function configureFormFields(FormMapper $formMapper)
- {
- $formMapper
- ->add('title', 'text', array('label' => 'Post Title'))
- ->add('author', 'entity', array('class' => 'Acme\DemoBundle\Entity\User'))
- ->add('body') //if no type is specified, SonataAdminBundle tries to guess it
- ;
- }
- // Fields to be shown on filter forms
- protected function configureDatagridFilters(DatagridMapper $datagridMapper)
- {
- $datagridMapper
- ->add('title')
- ->add('author')
- ;
- }
- // Fields to be shown on lists
- protected function configureListFields(ListMapper $listMapper)
- {
- $listMapper
- ->addIdentifier('title')
- ->add('slug')
- ->add('author')
- ;
- }
- }
- Internally, the provided ``Admin`` class will use these three functions to create three
- ``FieldDescriptionCollection`` instances:
- * ``$formFieldDescriptions``, containing three ``FieldDescriptionInterface`` instances
- for title, author and body
- * ``$filterFieldDescriptions``, containing two ``FieldDescriptionInterface`` instances
- for title and author
- * ``$listFieldDescriptions``, containing three ``FieldDescriptionInterface`` instances
- for title, slug and author
- The actual ``FieldDescription`` implementation is provided by the storage abstraction
- bundle that you choose during the installation process, based on the
- ``BaseFieldDescription`` abstract class provided by ``SonataAdminBundle``.
- Each ``FieldDescription`` contains various details about a field mapping. Some of
- them are independent of the action in which they are used, like ``name`` or ``type``,
- while other are used only in specific actions. More information can be found in the
- ``BaseFieldDescription`` class file.
- In most scenarios, you won't actually need to handle the ``FieldDescription`` yourself.
- However, it is important that you know it exists and how it's used, as it sits at the
- core of ``SonataAdminBundle``.
- Templates
- ---------
- Like most actions, ``CRUDController`` actions use view files to render their output.
- ``SonataAdminBundle`` provides ready to use views as well as ways to easily customize them.
- The current implementation uses ``Twig`` as the template engine. All templates
- are located in the ``Resources/views`` directory of the bundle.
- There are two base templates, one of these is ultimately used in every action:
- * ``SonataAdminBundle::standard_layout.html.twig``
- * ``SonataAdminBundle::ajax_layout.html.twig``
- Like the names say, one if for standard calls, the other one for AJAX.
- The subfolders include Twig files for specific sections of ``SonataAdminBundle``:
- Block:
- ``SonataBlockBundle`` block views. By default there is only has one, which
- displays all the mapped classes on the dashboard
- Button:
- Buttons such as ``Add new`` or ``Delete`` that you can see across several
- CRUD actions
- CRUD:
- Base views for every CRUD action, plus several field views for each field type
- Core:
- Dashboard view, together with deprecated and stub twig files.
- Form:
- Views related to form rendering
- Helper:
- A view providing a short object description, as part of a specific form field
- type provided by ``SonataAdminBundle``
- Pager:
- Pagination related view files
- These will be discussed in greater detail in the specific :doc:`templates` section, where
- you will also find instructions on how to configure ``SonataAdminBundle`` to use your templates
- instead of the default ones.
- Managing ``Admin`` Service
- ------------------------------
- Your ``Admin`` service definitions are parsed when Symfony2 is loaded, and handled by
- the ``Pool`` class. This class, available as the ``sonata.admin.pool`` service from the
- DIC, handles the ``Admin`` classes, lazy-loading them on demand (to reduce overhead)
- and matching each of them to a group. It's also responsible for handling the top level
- template files, administration panel title and logo.
- .. _`Django Project Website`: http://www.djangoproject.com/
- .. _`CRUD is an acronym`: http://en.wikipedia.org/wiki/CRUD
|