Exposición de lo que nos ofrece SonataAdminBundle y recorrido práctico desde su instalación, aprendiendo a personalizarlo y solventar diversos casos que nos encontramos con frecuencia en la implementación de un panel de administración con este bundle. Charla impartida en deSymfony 2016 (16-17 de septiembre, Madrid).
Segmentacion Segmantica_Modelos UNET and DEEPLABV3
SonataAdmin para Regalos
1.
2.
3. Trabajo en Limenius
Hacemos proyectos a medida
en Symfony y React
Raro es el proyecto que no
requiera un panel de
administración
Desde hace bastante
resolvemos esa parte con
SonataAdminBundle
Victoria Quirante
@vicqr
victoria@limenius.com
18. Lo que es y lo que no es Sonata
No es el David de Miguel Ángel
Ni la teoría de cuerdas
Ni el número áureo
19. Lo que es y lo que no es Sonata
No es el David de Miguel Ángel
Ni la teoría de cuerdas
Ni el número áureo
Pero sí es algo muy útil
20. Lo que es y lo que no es Sonata
No es el David de Miguel Ángel
Ni la teoría de cuerdas
Ni el número áureo
Pero sí es algo muy útil
Como Symfony, como PHP
21. Charla práctica
- No es una revisión exhaustiva de la documentación
- Vamos a mostrar cómo se usa en la práctica
- Cuál es el recorrido desde la instalación limpia
22. Charla práctica
- No es una revisión exhaustiva de la documentación
- Vamos a mostrar cómo se usa en la práctica
- Cuál es el recorrido desde la instalación limpia
1) Qué te da Sonata “gratis”
2) Cómo personalizo lo que quiera a partir de ahí
32. El Admin básico: 3 pasos, 2 minutos
Tenemos la entidad Regalo para la que queremos
crear un Admin
33. El Admin básico: 3 pasos, 2 minutos
Tenemos la entidad Regalo para la que queremos
crear un Admin:
1) Creamos la clase RegaloAdmin
2) Registramos el servicio
34. El Admin básico - Paso 1: Creamos la clase Admin
# src/AppBundle/Admin/RegaloAdmin.php
class RegaloAdmin extends Admin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper->add('nombre');
}
protected function configureDatagridFilters(DatagridMapper
$datagridMapper)
{
$datagridMapper->add('nombre');
}
protected function configureListFields(ListMapper $listMapper)
{
$listMapper->addIdentifier('nombre');
}
}
35. El Admin básico - Paso 1: Creamos la clase Admin
# src/AppBundle/Admin/RegaloAdmin.php
class RegaloAdmin extends Admin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper->add('nombre');
}
protected function configureDatagridFilters(DatagridMapper
$datagridMapper)
{
$datagridMapper->add('nombre');
}
protected function configureListFields(ListMapper $listMapper)
{
$listMapper->addIdentifier('nombre');
}
}
36. El Admin básico - Paso 1: Creamos la clase Admin
# src/AppBundle/Admin/RegaloAdmin.php
class RegaloAdmin extends Admin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper->add('nombre');
}
protected function configureDatagridFilters(DatagridMapper
$datagridMapper)
{
$datagridMapper->add('nombre');
}
protected function configureListFields(ListMapper $listMapper)
{
$listMapper->addIdentifier('nombre');
}
}
37. El Admin básico - Paso 1: Creamos la clase Admin
# src/AppBundle/Admin/RegaloAdmin.php
class RegaloAdmin extends Admin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper->add('nombre');
}
protected function configureDatagridFilters(DatagridMapper
$datagridMapper)
{
$datagridMapper->add('nombre');
}
protected function configureListFields(ListMapper $listMapper)
{
$listMapper->addIdentifier('nombre');
}
}
38. El Admin básico - Paso 1: Creamos la clase Admin
# src/AppBundle/Admin/RegaloAdmin.php
class RegaloAdmin extends Admin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper->add('nombre');
}
protected function configureDatagridFilters(DatagridMapper
$datagridMapper)
{
$datagridMapper->add('nombre');
}
protected function configureListFields(ListMapper $listMapper)
{
$listMapper->addIdentifier('nombre');
}
}
93. Una collection en el form (one-to-many)
# src/AppBundle/Admin/CompradorAdmin.php
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->with('Datos personales', array('class' => 'col-md-6'))
->add('nombre')
->add('apellidos')
->end()
;
}
94. Una collection en el form (one-to-many)
# src/AppBundle/Admin/CompradorAdmin.php
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->with('Datos personales', array('class' => 'col-md-6'))
->add('nombre')
->add('apellidos')
->end()
->with('Pagos', array('class' => 'col-md-6'))
->add('pagos', 'sonata_type_collection', array(
), array(
'edit' => 'inline',
'inline' => 'table',
))
->end()
;
}
95. Una collection en el form (one-to-many)
# src/AppBundle/Admin/CompradorAdmin.php
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->with('Datos personales', array('class' => 'col-md-6'))
->add('nombre')
->add('apellidos')
->end()
->with('Pagos', array('class' => 'col-md-6'))
->add('pagos', 'sonata_type_collection', array(
), array(
'edit' => 'inline',
'inline' => 'table',
))
->end()
;
}
96. Una collection en el form (one-to-many)
# src/AppBundle/Admin/CompradorAdmin.php
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->with('Datos personales', array('class' => 'col-md-6'))
->add('nombre')
->add('apellidos')
->end()
->with('Pagos', array('class' => 'col-md-6'))
->add('pagos', 'sonata_type_collection', array(
), array(
'edit' => 'inline',
'inline' => 'table',
))
->end()
;
}
Y creamos un Admin para la entidad Pago
112. ¿Tenemos mucho o poco?
- Con muy poco esfuerzo tienes muchísimo
- De hecho tienes la mayor parte de lo que necesitas
- Pero el mundo no es perfecto, y vas a necesitar
algunas otras cosas en tu panel casi con seguridad
113.
114. ¿Y si quiero...
… tener un formulario maquetado de otra forma?
… meter algo “extraño” en un campo del listado?
… crear una sección del menú que no sea un listado?
… meter algo dentro de Sonata que no tenga nada que
ver con el panel de administración…?
115. ¿Y si quiero...
… tener un formulario maquetado de otra forma?
… meter algo “extraño” en un campo del listado?
… crear una sección del menú que no sea un listado?
… meter algo dentro de Sonata que no tenga nada que
ver con el panel de administración…?
¿Cuánto me va a costar todo eso? ¿No
será mejor empezar de cero?
134. Sobrescribir la template de un field en el list
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
...
;
}
135. Sobrescribir la template de un field en el list (paso 1)
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
...
->add('miField', 'string', array('template' =>
':Admin:field_envio_email.html.twig'))
;
}
136. Sobrescribir la template de un field en el list (paso 1)
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
...
->add('miField', 'string', array('template' =>
':Admin:field_envio_email.html.twig'))
;
}
137. Sobrescribir la template de un field en el list (paso 2)
# app/Resources/views/Admin/field_envio_email.html.twig
{% extends 'SonataAdminBundle:CRUD:base_list_field.html.twig' %}
{% block field %}
<a class="btn btn-primary btn-sm" href="">
<i class="fa fa-envelope"></i> Enviar
</a>
{% endblock %}
155. Crear un action custom (paso 1)
# src/AppBundle/Controller/RegaloAdminController.php
use SonataAdminBundleControllerCRUDController as Controller;
use SymfonyComponentHttpFoundationRedirectResponse;
class RegaloAdminController extends Controller
{
public function sendEmailAction()
{
$regalo = $this->admin->getSubject();
$email = $regalo->getDestinatario()->getEmail();
// Here code to send email
$this->addFlash('sonata_flash_success', 'Email enviado a
'.$email);
return new RedirectResponse($this->admin->generateUrl('list'));
}
}
156. Crear un action custom (paso 1)
# src/AppBundle/Controller/RegaloAdminController.php
use SonataAdminBundleControllerCRUDController as Controller;
use SymfonyComponentHttpFoundationRedirectResponse;
class RegaloAdminController extends Controller
{
public function sendEmailAction()
{
$regalo = $this->admin->getSubject();
$email = $regalo->getDestinatario()->getEmail();
// Here code to send email
$this->addFlash('sonata_flash_success', 'Email enviado a
'.$email);
return new RedirectResponse($this->admin->generateUrl('list'));
}
}
157. Crear un action custom (paso 1)
# src/AppBundle/Controller/RegaloAdminController.php
use SonataAdminBundleControllerCRUDController as Controller;
use SymfonyComponentHttpFoundationRedirectResponse;
class RegaloAdminController extends Controller
{
public function sendEmailAction()
{
$regalo = $this->admin->getSubject();
$email = $regalo->getDestinatario()->getEmail();
// Here code to send email
$this->addFlash('sonata_flash_success', 'Email enviado a
'.$email);
return new RedirectResponse($this->admin->generateUrl('list'));
}
}
166. Crear un batch action custom (paso 1)
# src/AppBundle/Controller/RegaloAdminController.php
public function batchActionSendEmail($selectedModelQuery)
{
// Here code to send emails
return new RedirectResponse($this->admin->generateUrl('list'));
}
167. Crear un batch action custom (paso 1)
# src/AppBundle/Controller/RegaloAdminController.php
public function batchActionSendEmail($selectedModelQuery)
{
// Here code to send emails
return new RedirectResponse($this->admin->generateUrl('list'));
}
168. Crear un batch action custom (paso 2)
# src/AppBundle/Admin/RegaloAdmin.php
public function getBatchActions()
{
$actions = parent::getBatchActions();
if ($this->hasRoute('edit') && $this->isGranted('EDIT')) {
$actions['send_email'] = [
'label' => 'Enviar email',
'ask_confirmation' => false,
];
}
return $actions;
}
169. Crear un batch action custom (paso 2)
# src/AppBundle/Admin/RegaloAdmin.php
public function getBatchActions()
{
$actions = parent::getBatchActions();
if ($this->hasRoute('edit') && $this->isGranted('EDIT')) {
$actions['send_email'] = [
'label' => 'Enviar email',
'ask_confirmation' => false,
];
}
return $actions;
}
199. Crear dos admins de la misma entidad
# src/AppBundle/Admin/RegaloPasadoAdmin.php
class RegaloPasadoAdmin extends Admin
{
}
Sin problema. Creamos una nueva clase
Admin…
200. Crear dos admins de la misma entidad
# src/AppBundle/Admin/RegaloPasadoAdmin.php
class RegaloPasadoAdmin extends Admin
{
protected $baseRouteName = 'regalo_pasado';
protected $baseRoutePattern = 'regalo-pasado'
...
}
(sin olvidar estas propiedades para que Sonata
no se líe con el routing)
201. Crear dos admins de la misma entidad
# app/config/services.yml
services:
admin.regalo:
class: AppBundleAdminRegaloAdmin
arguments: [~, AppBundleEntityRegalo, AppBundle:RegaloAdmin]
tags:
- { name: sonata.admin, manager_type: orm, label: Regalos }
calls:
- [ setTemplate, [edit, :Admin:edit_regalo.html.twig]]
… y registramos el nuevo servicio
202. Crear dos admins de la misma entidad
# app/config/services.yml
services:
admin.regalo:
class: AppBundleAdminRegaloAdmin
arguments: [~, AppBundleEntityRegalo, AppBundle:RegaloAdmin]
tags:
- { name: sonata.admin, manager_type: orm, label: Activos }
calls:
- [ setTemplate, [edit, :Admin:edit_regalo.html.twig]]
admin.regalo_pasado:
class: AppBundleAdminRegaloPasadoAdmin
arguments: [~, AppBundleEntityRegalo, ~]
tags:
- { name: sonata.admin, manager_type: orm, label: Pasados }
… y registramos el nuevo servicio
217. Enlazar un action custom desde la sidebar
Creamos nuestro action custom, la template
y la ruta...
218. Enlazar un action custom desde la sidebar
# app/config/config.yml
dashboard:
groups:
...
demo.admin.settings:
label: Configuración
label_catalogue: AppBundle
icon: '<i class="fa fa-gear"></i>'
items:
- admin.configuracion
Creamos nuestro action custom, la template
y la ruta...
… la enlazamos desde el sidebar
219. Enlazar un action custom desde la sidebar
# app/config/config.yml
dashboard:
groups:
...
demo.admin.settings:
label: Configuración
label_catalogue: AppBundle
icon: '<i class="fa fa-gear"></i>'
items:
- admin.configuracion
- route: config_myEdit
label: 'Mi configuración'
Creamos nuestro action custom, la template
y la ruta...
… la enlazamos desde el sidebar
222. Toda tu aplicación puede estar dentro de Sonata
Tu aplicación puede tener partes que no
sean un Admin
Y sin embargo estén integradas con lo
demás
Puedes meter cualquier cosa ahí dentro
225. Toda tu aplicación puede estar dentro de Sonata
Creas tu action en el controlador (PacienteAdminController.php)
226. Toda tu aplicación puede estar dentro de Sonata
Creas tu action en el controlador (PacienteAdminController.php)
Configuras tu ruta en configureRoutes (PacienteAdmin.php)
$collection->add('editor', $this->getRouterIdParameter().'/editor');
227. Toda tu aplicación puede estar dentro de Sonata
Creas tu action en el controlador (PacienteAdminController.php)
Configuras tu ruta en configureRoutes (PacienteAdmin.php)
$collection->add('editor', $this->getRouterIdParameter().'/editor');
Haces setTemplate en la declaración del servicio (services.yml)
<call method="setTemplates">
<argument type="collection">
<argument key="editor">:editor:editor.html.twig</argument>
</argument>
</call>
228. V. Más allá
O qué otras cosas
hay ahí fuera y
dónde puedo
encontrarlas
230. FOSUserBundle & SonataUserAdminBundle
SonataUserAdminBundle es una capa sobre
FOSUserBundle que aporta algunas cosas
(pero no es imprescindible para usar
FOSUserBundle)
https://sonata-project.org/bundles/user/3-x/doc/reference/introduction.html
232. Eventos
https://sonata-project.org/bundles/admin/3-x/doc/reference/events.html
Hay una serie de eventos definidos por
Sonata que pueden resultar muy útiles
● sonata.admin.event.persistence.pre_update
● sonata.admin.event.persistence.post_update
● sonata.admin.event.persistence.pre_persist
● sonata.admin.event.persistence.post_persist
● sonata.admin.event.persistence.pre_remove
● sonata.admin.event.persistence.post_remove
240. Conclusiones
● Los principales problemas se han ido
solucionando. Y sigue mejorando.
● Te da MUCHO hecho. Hay que sacar el
máximo provecho a esa parte.
241. Conclusiones
● Los principales problemas se han ido
solucionando. Y sigue mejorando.
● Te da MUCHO hecho. Hay que sacar el
máximo provecho a esa parte.
● Puedes sobrescribir lo que quieras y meter tu
propio código donde quieras.
245. Victoria Quirante Ruiz Madrid, 16-17 Sep. 2016#deSymfony
@vicqr
victoria@limenius.com
https://github.com/VictoriaQ/sonatademo
Formación, consultoría y
desarrollo de proyectos
246. Victoria Quirante Ruiz Madrid, 16-17 Sep. 2016#deSymfony
@vicqr
victoria@limenius.com
https://github.com/VictoriaQ/sonatademo
Formación, consultoría y
desarrollo de proyectos
Gracias!