2. Who am I ?
• Thomas Rabaix
• Speaker at Symfony Live Conferences
• Author of many symfony1 plugins
• lead developer of the sonata project
• Working at Ekino, a french web agency
3. Talk
• Sonata Project presentation
• Quick Tour
• Under the hood
• Customize / Advanced features
• Conclusion
4. Sonata Project
• A not so young project
• Based on symfony1 plugins
• Recoded with the best practices of
Symfony2
• Built on top on very strong and powerful
framework
5. Sonata Project
• An ecommerce toolbox
• How :
• avoiding reinvented the wheel
• contribution to the community
• built on top of a strong framework
6. Sonata’s bundles
• PageBundle : a page manager with block
as service and strong caching mechanism
• MediaBundle : a media manager on
steroid, you don’t have to worry about
managing files or videos
• UserBundle, IntlBundle, etc ...
• AdminBundle : A backend generator
9. • No admin generator for Symfony 2.0
• Frustrating by the admin generator provided by
symfony1
• Admin is not only about Model; but about
providing a consistent and rich user
experience for managing data.
20. Other Features
• Permissions management
• Flash messages
• Nested Admin
• Command lines utilities
• Translated into more than10 languages
21. Quick Tour Summary
• Dashboard
• Consistent Interface across bundles
• Easy to configure, but powerful for
advanced users
• Advanced features
• Inspired from the django admin module
(user interactions)
22. Under the hood
http://www.flickr.com/photos/52251564@N08/5937620090
23. Admin Class Dependencies
Security Builder
Sonata Admin Bundle
List
Symfony Framework
Translator
Datagrid
Admin Show
Routing
class Form
Validator
Model
Manager
Form
24. Security
• Based on the SecurityHandlerInterface
• 2 built-in implementations
• NoopSecurityHandler : use the
Symfony’s firewall
• AclSecurityHandler : based on ACL
- Advanced users only
25. Security
• Admin Usage
1. protected function configureFormFields(FormMapper $formMapper)
2. {
3. $formMapper
4. ->with('General')
5. ->add('enabled', null, array('required' => false))
6. ->add('author', 'sonata_type_model', array(), array('edit' => 'list'))
7. ->add('title')
8. ->end()
9. ;
10.
11. if (!$this->isGranted('CREATE')) {
12. // do specific code if the user cannot create a new object
13. }
14. }
• Template Usage
1. {% if admin.isGranted('CREATE') %}
2. // DO YOUR STUFF
3. {% endif %}
26. Security : ACL
• Required to have a custom external bundle to
manage permissions and user : see FOS/
UserBundle and Sonata/UserBundle
• Built on top of a custom MaskBuilder (basic
roles : List,View, Edit, Create, Delete)
• Command lines :
• php app/console init:acl
• php app/console sonata:admin:setup-acl
27. Routing
• Definition set from the Admin class
• Can be tweaked by the configureRoute
1. /**
2. * @param SonataAdminBundleRouteRouteCollection $collection
3. * @return void
4. */
5. protected function configureRoutes(RouteCollection $collection)
6. {
7. $collection->add('snapshots'); Add the id parameter
8. $collection->remove('edit');
9.
10. $collection->add('test', $this->getRouterIdParameter().'/test');
11. }
• Template Usage
1. <a href="{{ admin.generateUrl('view', { 'id' : media.id, 'format' : 'reference'}) }}">reference</a>
2. <a href="{{ admin.generateObjectUrl(media, 'view', {'format' : 'reference'}) }}">reference</a>
28. Admin Model Manager
• Persistency layer abstraction for Admin Bundle.
• All Persistencies actions are done in the Model
Manager
• delete, query, pagination, etc..
• form type manipulation delegation
• For now only Doctrine ORM (Propel and
Doctrine ODM are work in progress by external
contributors)
29. Admin Model Manager
• Some bundle provides custom Model Manager
• You can define your own proxy Admin Model
Manager to reuse the Bundle Model Manager
• Use case : Sonata Media Bundle (delete action)
30. Model Manager 1. class AdminModelManager extends ModelManager {
2. protected $manager;
Sonata Media Bundle 3.
4. public function __construct($entityManager, $manager) {
5. parent::__construct($entityManager);
2 Model Managers : 6. $this->manager = $manager;
- entity : deal with deletion and so on ... 7. }
8.
- admin : proxy some methods to the entity 9. public function delete($object) {
10. $this->manager->delete($object);
11. }
How to ? 12. }
1. create a dedicated Admin Model Manager 1. class BundleMediaManager extends AbstractMediaManager {
2. create a Bundle Model Manager 1. public function delete(MediaInterface $media) {
2. $this->pool
3. redefine only required methods 3. ->getProvider($media->getProviderName())
4. define services 4. ->preRemove($media);
5. $this->em->remove($media);
6. $this->em->flush();
Delete thumbnails
7.
8. $this->pool
9. ->getProvider($media->getProviderName())
10. ->postRemove($media);
11. $this->em->flush();
12. }
2. }
1. <service id="sonata.media.admin.media" class="SonataMediaBundleEntityBundleMediaManager">
2. <tag name="sonata.admin" manager_type="orm" group="sonata_media" label="media"/>
3. <argument />
4. <argument>%sonata.media.admin.media.entity%</argument>
5. <argument>%sonata.media.admin.media.controller%</argument>
6.
7. <call method="setModelManager">
8. <argument type="service" id="sonata.media.admin.media.manager" />
9. </call>
10. </service>
11.
12. <service id="sonata.media.admin.media.manager" class="SonataMediaBundleAdminManagerDoctrineModelManager">
13. <argument type="service" id="doctrine.orm.default_entity_manager" />
14. <argument type="service" id="sonata.media.manager.media" />
15. </service>
31. Translator
• 2 catalogues
• SonataAdminBundle used to translate
shared messages
• messages used to translate current Admin
1. $formMapper
2. ->with($this->trans('form_page.group_main_label'))
3. ->add('name')
4. ->end()
5. ;
• Can be set by updating the translationDomain
property
32. Form
• Originally built on the the first implementation
• Too bad ..... major refactoring 3 months later
• Some admin features has been removed or still
broken :(
• But the new form implementation is pretty
awesome .... once you know how to use it.
33. Form Mapper
• Interact with the FormMapper
• Proxy class between the Admin Class and the
Symfony Form Component
• Act as the Symfony FormBuilder component
• You can use your custom field types
34. Core types
Form Type Model Manager Types
Form Types
• AdminType : used to embedded form from
another Admin class
• CollectionType : use by one-to-many association
• ModelType : select choice (like EntityType)
• ModelReferenceType : handle an model id
• ImmutableArrayType : specify a form type per
array element
1. $formMapper->add('settings', 'sonata_type_immutable_array', array(
2. 'keys' => array(
3. array('layout', 'textarea', array()),
4. array('action', 'text', array()),
5. array('parameters', 'text', array()),
6. )
7. ));
35. Validator
• Assert rules can be defined in the validation.
[xml|yml] files (validator component)
nothing new ...
• Conditional Validation
36. Conditional Validation
• Not mandatory, but allow to add inline validation
a runtime.
• ex : check only if a value is set
• Validate method inside the admin class
• Interact with a new ErrorElement object
• The ErrorElement is just a validator service based
on the Validator Component
41. Form : one-to-many
• Type : sonata_type_collection (CollectionType)
• Form Option
by_reference => false
• Sonata Options
• edit : standard / inline
• inline : table | list
• position : field name (if exists)
42. Form : many-to-many
• Type : sonata_type_model (ModelType)
• Sonata Options
• no options
43. Form : many-to-one
• Type : sonata_type_model (ModelType)
• Form Options :
• expanded : true|false
• Sonata Options
• edit : standard (select box) / list (popup)
• link_parameters : add extra link parameters to
the link
44. Form : many-to-one
• Type : sonata_type_admin (AdminType)
• Embed an admin form for an entity into the current
admin
• Sonata Options
• no option!
45. Form Theme
• Based on the form theme mechanism
• Define a getFormTheme()
• a set of form templates
• allows to customize an admin form
46. Form Theme
• Just define a custom block with the correct name ...
• How to know the block name ... ?
• Provide a custom `block_name` option
• or use a defined built-in pattern :
admin_service_id_[type]_[widget|label|errors|row]
admin_service_id_[fieldName]_[widget|label|errors|row]
47. Form block
• Theme definition
1. protected $formTheme = array(
2. 'SonataAdminBundle:Form:form_admin_fields.html.twig',
3. 'SonataNewsBundle:Form:form.html.twig'
4. );
• Block definition
1.{% block sonata_user_admin_user_credentialsExpired_text_widget %}
2. PUT HERE THE WIDGET ...
3.{% endblock %}
• Et voila!
49. CRUD Controller
• Use the admin class to generate required
objects
• contains create, edit, update, delete and
batch actions
• can be extended to change some logic
• use case : Sonata Media Bundle
50. Custom CRUD Controller
1. namespace SonataMediaBundleController;
2.
3. use SonataAdminBundleControllerCRUDController as Controller; Grant check
4. use SymfonyComponentSecurityCoreExceptionAccessDeniedException;
5.
6. class MediaAdminController extends Controller {
7. public function createAction() {
8. if (false === $this->admin->isGranted('CREATE')) {
9. throw new AccessDeniedException();
10. }
11.
12. $parameters = $this->admin->getPersistentParameters();
13.
14. if (!$parameters['provider']) {
Custom Template
15. return $this-
>render('SonataMediaBundle:MediaAdmin:select_provider.html.twig', array(
16. 'providers' => $this->get('sonata.media.pool')
17. ->getProvidersByContext($this->get('request')-
>get('context', 'default')),
18. 'base_template' => $this->getBaseTemplate(),
19. 'admin' => $this->admin,
20. 'action' => 'create'
21. ));
22. }
23.
24. return parent::createAction();
25. }
26.}
Parent action
51. Nested Admin
• clean url : /admin/sonata/news/post/1/comment/list
• reuse other admin definition
• autofilter with the targeted elements
• only work on one level
• You don’t need to know routing name, as long as
you use the admin class
54. Admin Extension
• Allow to add extra feature or redefine some field to
the admin
• Good entry point if you extends some entities
• Add extension must implement the
AdminExtensionInterface and define as
service with the sonata.admin.extension
55. Debug
• Check out external configurations
• validator configuration
• doctrine schema definition
• use firebug to check Ajax errors (missing toString method or
type hinting)
• Get information from the Admin command tools
• sonata:admin:list
• sonata:admin:explain
59. small numbers
• First commit in
november 2010
• 650 commits
• 49 Contributors!
• 14 Translations
Thanks!
60. What’s next ?
• Version 1
• Stabilize the AdminBundle
• Add more tests... : 56 tests, 145
assertions
• Version 1.1
• Add missing features from the original
form factoring
• Add more layer persistency
(contribution)