Explorar o código

Added cookbook entry on using DataMapper with admin classes. (#4566)

Oleksandr Zanichkovskyi %!s(int64=7) %!d(string=hai) anos
pai
achega
65060087ae
Modificáronse 2 ficheiros con 140 adicións e 0 borrados
  1. 139 0
      Resources/doc/cookbook/recipe_data_mapper.rst
  2. 1 0
      Resources/doc/index.rst

+ 139 - 0
Resources/doc/cookbook/recipe_data_mapper.rst

@@ -0,0 +1,139 @@
+Using DataMapper to work with domain entities without per field setters
+=======================================================================
+
+This is an example of using DataMapper with entities that avoid setters/getters for each field.
+
+Pre-requisites
+--------------
+
+- You already have SonataAdmin and DoctrineORM up and running.
+- You already have an Entity class, in this example that class will be called ``Example``.
+- You already have an Admin set up, in this example it's called ``ExampleAdmin``.
+
+The recipe
+----------
+
+If there is a requirement for the entity to have domain specific methods instead of getters/setters for each
+entity field then it won't work with SonataAdmin out of the box. But Symfony Form component provides ``DataMapper``
+that can be used to make it work. Symfony itself lacks examples of using ``DataMapper`` but there is an article by
+webmozart that covers it - https://webmozart.io/blog/2015/09/09/value-objects-in-symfony-forms/
+
+Example Entity
+^^^^^^^^^^^^^^
+
+.. code-block:: php
+
+    <?php
+
+    // src/AppBundle/Entity/Example.php
+
+    namespace AppBundle\Entity;
+
+    class Example
+    {
+        private $name;
+
+        private $description;
+
+        public function __construct($name, $description)
+        {
+            $this->name = $name;
+            $this->description = $description;
+        }
+
+        public function update($description)
+        {
+            $this->description = $description
+        }
+
+        // rest of the code goes here
+    }
+
+DataMapper
+^^^^^^^^^^
+
+To be able to set entity data without the possibility to use setters a ``DataMapper`` should be created.
+
+.. code-block:: php
+
+    <?php
+
+    // src/AppBundle/Form/DataMapper/ExampleDataMapper.php
+
+    namespace AppBundle\Form\DataMapper;
+
+    use Symfony\Component\Form\DataMapperInterface;
+    use AppBundle\Entity\Example;
+
+    class ExampleDataMapper implements DataMapperInterface
+    {
+        /**
+         * @param Example $data
+         * @param FormInterface[]|\Traversable $forms
+         */
+        public function mapDataToForms($data, $forms)
+        {
+            if (null !== $data) {
+                $forms = iterator_to_array($forms);
+                $forms['name']->setData($data->getName());
+                $forms['description']->setData($data->getDescription());
+            }
+        }
+
+        /**
+         * @param FormInterface[]|\Traversable $forms
+         * @param Example $data
+         */
+        public function mapFormsToData($forms, &$data)
+        {
+            $forms = iterator_to_array($forms);
+
+            if (null === $data->getId()) {
+                $name = $forms['name']->getData();
+                $description = $forms['description']->getData();
+
+                // New entity is created
+                $data = new Example(
+                    $name,
+                    $description
+                );
+            } else {
+                $data->update(
+                    $forms['description']->getData()
+                );
+            }
+        }
+    }
+
+Admin class
+^^^^^^^^^^^
+
+Now we need to configure the form to use our ``ExampleDataMapper``.
+
+.. code-block:: php
+
+    <?php
+
+    // src/AppBundle/Admin/ExampleAdmin.php
+
+    namespace AppBundle\Admin;
+
+    use Sonata\AdminBundle\Admin\AbstractAdmin;
+    use Sonata\AdminBundle\Form\FormMapper;
+    use AppBundle\Form\DataMapper\ExampleDataMapper;
+
+    class ExampleAdmin extends AbstractAdmin
+    {
+        protected function configureFormFields(FormMapper $formMapper)
+        {
+            $formMapper
+                ->add('name', null)
+                ->add('description', null);
+            ;
+
+            $builder = $formMapper->getFormBuilder();
+            $builder->setDataMapper(new ExampleDataMapper());
+        }
+
+        // ...
+    }

+ 1 - 0
Resources/doc/index.rst

@@ -94,3 +94,4 @@ The demo website can be found at http://demo.sonata-project.org.
    cookbook/recipe_lock_protection
    cookbook/recipe_sortable_sonata_type_model
    cookbook/recipe_delete_field_group
+   cookbook/recipe_data_mapper