cómo domar sonataadminbundle
TRANSCRIPT
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
I. Introducción
O acerca de por qué y para qué estamos aquí
El creador
Principales colaboradores
Principales problemas históricamente atribuidos
- Difícil de instalar
Principales problemas históricamente atribuidos
- Difícil de instalar- Feo
Principales problemas históricamente atribuidos
- Difícil de instalar- Feo- Mala documentación
Principales problemas históricamente atribuidos
- Difícil de instalar- Feo- Mala documentación- Mucho código, difícil de investigar
Principales problemas históricamente atribuidos
- Difícil de instalar- Feo- Mala documentación- Mucho código, difícil de investigar
Principales problemas históricamente atribuidos
- Difícil de instalar- Feo- Mala documentación- Mucho código, difícil de investigar
Principales problemas históricamente atribuidos
- Difícil de instalar- Feo- Mala documentación regular- Mucho código, difícil de investigar
Principales problemas históricamente atribuidos
- Difícil de instalar- Feo- Mala documentación regular- Mucho código, difícil de investigar
El problema que queremos resolver...
...es implementar un panel de administración
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
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
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 útilComo Symfony, como PHP
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
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í
Dos tipos de desarrolladores
Charla práctica
https://github.com/VictoriaQ/sonatademo
II. El Admin básico
O cómo sacar provecho del sudor de otros de forma que llega a dar hasta un poco de vergüenza
Screenshots (II): Instalación limpia
Screenshots (II): Instalación limpia
Screenshots (II): Instalación limpia
¿Cómo empezamos?
El Admin básico: 3 pasos, 2 minutos
Tenemos la entidad Regalo para la que queremos crear un Admin
El Admin básico: 3 pasos, 2 minutos
Tenemos la entidad Regalo para la que queremos crear un Admin:
1) Creamos la clase RegaloAdmin2) Registramos el servicio
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');
}
}
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');
}
}
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');
}
}
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');
}
}
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');
}
}
El Admin básico - Paso 2: Registramos el servicio
# app/config/services.yml
services: admin.regalo: class: AppBundle\Admin\RegaloAdmin arguments: [~, AppBundle\Entity\Regalo, ~] tags: - { name: sonata.admin, manager_type: orm, label: Regalos }
El Admin básico - Paso 2: Registramos el servicio
# app/config/services.yml
services: admin.regalo: class: AppBundle\Admin\RegaloAdmin arguments: [~, AppBundle\Entity\Regalo, ~] tags: - { name: sonata.admin, manager_type: orm, label: Regalos }
Screenshots (II): Primer Admin
Screenshots (II): Primer Admin
Screenshots (II): Primer Admin
Screenshots (II): Primer Admin
El Admin básico - Paso 3 (opcional): Menú lateral
# app/config/config.yml
sonata_admin: dashboard: groups: demo.admin.main: label: Admin label_catalogue: AppBundle icon: '<i class="fa fa-database"></i>' items: - admin.regalo
El Admin básico - Paso 3 (opcional): Menú lateral
# app/config/config.yml
sonata_admin: dashboard: groups: demo.admin.main: label: Admin label_catalogue: AppBundle icon: '<i class="fa fa-database"></i>' items: - admin.regalo
El Admin básico - Paso 3 (opcional): Menú lateral
# app/config/config.yml
sonata_admin: dashboard: groups: demo.admin.main: label: Admin label_catalogue: AppBundle icon: '<i class="fa fa-database"></i>' items: - admin.regalo
Screenshots (II): Primer Admin (ítem en menú lateral)
Ok, ¿y con eso que tengo?
¿Y con eso qué tengo?
- Create, edit, delete...
Screenshots (II): Primer Admin - El formulario
Lo que Sonata te da hecho
- Create, edit, delete...- Listado paginado, ordenable, filtrable
y exportable
Lo que Sonata te da hecho
- Create, edit, delete...
- Listado paginado, ordenable, filtrable y exportable
Screenshots (II): Primer Admin - El listado
Screenshots (II): Primer Admin - El listado
Screenshots (II): Primer Admin - Los filtros
Configuración básica del listado
Configuración básica del listado
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureListFields(ListMapper $listMapper) { $listMapper ->add('nombre')
; }
Configuración básica del listado
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureListFields(ListMapper $listMapper) { $listMapper ->add('nombre') ->add('precio') ->add('descripcion') ->add('destinatario') ->add('comprador') ; }
Configuración básica del listado
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureListFields(ListMapper $listMapper) { $listMapper ->addIdentifier('nombre') ->add('precio') ->add('descripcion') ->add('destinatario') ->add('comprador') ; }
Configuración básica del listado
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureListFields(ListMapper $listMapper) { $listMapper ->addIdentifier('nombre') ->add('precio', 'currency', array('currency' => 'EUR')) ->add('descripcion') ->add('destinatario') ->add('comprador') ; }
Configuración básica del listado
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureListFields(ListMapper $listMapper) { $listMapper ->addIdentifier('nombre') ->add('precio', 'currency', array('currency' => 'EUR')) ->add('descripcion', null, array('label' => 'Descripción')) ->add('destinatario') ->add('comprador') ; }
Configuración básica del listado
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureListFields(ListMapper $listMapper) { $listMapper ->addIdentifier('nombre') ->add('precio', 'currency', array('currency' => 'EUR')) ->add('descripcion', null, array('label' => 'Descripción')) ->add('destinatario', null, array('editable' => true) ->add('comprador') ; }
Configuración básica del listado
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureListFields(ListMapper $listMapper) { $listMapper ->addIdentifier('nombre') ->add('precio', 'currency', array('currency' => 'EUR')) ->add('descripcion', null, array('label' => 'Descripción')) ->add('destinatario', null, array('editable' => true)) ->add('comprador') ; }
https://sonata-project.org/bundles/admin/3-x/doc/reference/field_types.html
Screenshots (II): Primer Admin - El listado
Screenshots (II): Primer Admin - El listado
Screenshots (II): Primer Admin - El listado
Screenshots (II): Primer Admin - El listado
Configuración básica del listado
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureListFields(ListMapper $listMapper) { $listMapper
... ->add('_action', null, array( 'actions' => array( 'show' => array(), 'edit' => array(), 'delete' => array(), ) )) ; }
Configuración básica del listado
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureListFields(ListMapper $listMapper) { $listMapper
... ->add('_action', null, array( 'actions' => array( 'show' => array(), 'edit' => array(), 'delete' => array(), ) )) ; }
Screenshots (II): Primer Admin - El listado
Screenshots (II): Primer Admin - El listado
Configuración básica del formulario
Configuración básica del formulario
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureFormFields(FormMapper $formMapper) { $formMapper ->add('nombre') ; }
Configuración básica del formulario
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureFormFields(FormMapper $formMapper) { $formMapper ->add('nombre') ->add('precio') ->add('descripcion') ->add('destinatario') ->add('comprador') ; }
Screenshots (II): Primer Admin - El formulario
Configuración básica del formulario
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureFormFields(FormMapper $formMapper) { $formMapper ->add('nombre') ->add('precio') ->add('descripcion') ->add('destinatario') ->add('comprador') ; }
Configuración básica del formulario
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureFormFields(FormMapper $formMapper) { $formMapper ->with('Regalo', array('class' => 'col-md-6')) ->add('nombre') ->add('precio') ->add('descripcion') ->end() ->with('Participantes', array('class' => 'col-md-6')) ->add('destinatario') ->add('comprador') ->end() ; }
Configuración básica del formulario
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureFormFields(FormMapper $formMapper) { $formMapper ->with('Regalo', array('class' => 'col-md-6')) ->add('nombre') ->add('precio') ->add('descripcion') ->end() ->with('Participantes', array('class' => 'col-md-6')) ->add('destinatario') ->add('comprador') ->end() ; }
Screenshots (II): Primer Admin - El formulario
Configuración básica del formulario
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureFormFields(FormMapper $formMapper) { $formMapper ->tab('Tab 1') ->with('Regalo', array('class' => 'col-md-6')) ->add('nombre') ->add('precio') ->add('descripcion') ->end() ->with('Participantes', array('class' => 'col-md-6')) ->add('destinatario') ->add('comprador') ->end() ->end() ->tab('Tab 2') ->end() ; }
Screenshots (II): Primer Admin - El formulario
¿Y si alguno de los campos tiene una relación con otra entidad?
Screenshots (II): Primer Admin - El formulario
Configuración básica del formulario
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureFormFields(FormMapper $formMapper) { $formMapper
... ->with('Participantes', array('class' => 'col-md-6')) ->add('destinatario') ->add('comprador') ->end() ; }
Configuración básica del formulario
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureFormFields(FormMapper $formMapper) { $formMapper
... ->with('Participantes', array('class' => 'col-md-6')) ->add('destinatario', null) ->add('comprador', null) ->end() ; }
Configuración básica del formulario
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureFormFields(FormMapper $formMapper) { $formMapper
... ->with('Participantes', array('class' => 'col-md-6')) ->add('destinatario', 'entity', array( 'class' => 'AppBundle\Entity\Destinatario')) ->add('comprador', 'entity', array( 'class' => 'AppBundle\Entity\Comprador')) ->end() ; }
Configuración básica del formulario
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureFormFields(FormMapper $formMapper) { $formMapper
... ->with('Participantes', array('class' => 'col-md-6')) ->add('destinatario', null, array( 'class' => 'AppBundle\Entity\Destinatario', 'choice_label' => 'apellidos')) ->add('comprador', null, array( 'class' => 'AppBundle\Entity\Comprador', 'choice_label' => 'apellidos')) ->end() ; }
Configuración básica del formulario
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureFormFields(FormMapper $formMapper) { $formMapper
... ->with('Participantes', array('class' => 'col-md-6')) ->add('destinatario', null, array( 'class' => 'AppBundle\Entity\Destinatario', 'choice_label' => 'nombreCompleto')) ->add('comprador', null, array( 'class' => 'AppBundle\Entity\Comprador', 'choice_label' => 'nombreCompleto')) ->end() ; }
Screenshots (II): Primer Admin - El formulario
¿Y los one-to-many y many-to-many?
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()
; }
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() ; }
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() ; }
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
Una collection en el form (one-to-many)
Una collection en el form (one-to-many)
Una collection en el form (one-to-many)
Una many-to-many en el form
Una many-to-many en el form
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
...
->with('Establecimientos', array('class' => 'col-md-6'))
->add('tiendas', 'sonata_type_model', array(
'by_reference' => false,
'expanded' => true,
'multiple' => true,
'label' => 'Tiendas')
)
->end()
;
}
Una many-to-many en el form
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
...
->with('Establecimientos', array('class' => 'col-md-6'))
->add('tiendas', 'sonata_type_model', array(
'by_reference' => false,
'expanded' => true,
'multiple' => true,
'label' => 'Tiendas')
)
->end()
;
}
Una many-to-many en el form
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
...
->with('Establecimientos', array('class' => 'col-md-6'))
->add('tiendas', 'sonata_type_model', array(
'by_reference' => false,
'expanded' => true,
'multiple' => true,
'label' => 'Tiendas')
)
->end()
;
}
Una many-to-many en el form
Una many-to-many en el form
Una many-to-many en el form
Configuración básica de los filtros
Configuración básica de los filtros
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureDatagridFilters(DatagridMapper $datagridMapper) { $datagridMapper ->add('nombre') ; }
Configuración básica de los filtros
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureDatagridFilters(DatagridMapper $datagridMapper) { $datagridMapper ->add('nombre') ->add('precio') ->add('destinatario', null, array(), 'entity', array( 'class' => 'AppBundle\Entity\Destinatario', 'choice_label' => 'nombreCompleto')) ; }
Screenshots (II): Primer Admin - Los filtros
Hasta aquí lo “gratis”
¿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
¿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…?
¿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?
III. Personalizando
O cómo campar a mis anchas paso a paso
Personalizando
● Templates
● Queries
● Actions
Sobrescribiendo templates
Sobrescribir templates
# app/config/config.yml
sonata_admin: templates: user_block: 'SonataAdminBundle:Core:user_block.html.twig' add_block: 'SonataAdminBundle:Core:add_block.html.twig' layout: 'SonataAdminBundle::standard_layout.html.twig' ajax: 'SonataAdminBundle::ajax_layout.html.twig' dashboard: 'SonataAdminBundle:Core:dashboard.html.twig' search: 'SonataAdminBundle:Core:search.html.twig' list: 'SonataAdminBundle:CRUD:list.html.twig' show: 'SonataAdminBundle:CRUD:show.html.twig' show_compare: 'SonataAdminBundle:CRUD:show_compare.html.twig' edit: 'SonataAdminBundle:CRUD:edit.html.twig'
...
Sobrescribir templates
# app/config/config.yml
sonata_admin: templates: user_block: 'SonataAdminBundle:Core:user_block.html.twig' add_block: 'SonataAdminBundle:Core:add_block.html.twig' layout: 'SonataAdminBundle::standard_layout.html.twig' ajax: 'SonataAdminBundle::ajax_layout.html.twig' dashboard: 'SonataAdminBundle:Core:dashboard.html.twig' search: 'SonataAdminBundle:Core:search.html.twig' list: 'SonataAdminBundle:CRUD:list.html.twig' show: 'SonataAdminBundle:CRUD:show.html.twig' show_compare: 'SonataAdminBundle:CRUD:show_compare.html.twig' edit: 'SonataAdminBundle:CRUD:edit.html.twig'
...
https://sonata-project.org/bundles/admin/3-x/doc/reference/templates.html
Sobrescribir templates
# app/config/config.yml
sonata_admin: templates: user_block: 'SonataAdminBundle:Core:user_block.html.twig' add_block: 'SonataAdminBundle:Core:add_block.html.twig' layout: 'SonataAdminBundle::standard_layout.html.twig' ajax: 'SonataAdminBundle::ajax_layout.html.twig' dashboard: 'SonataAdminBundle:Core:dashboard.html.twig' search: 'SonataAdminBundle:Core:search.html.twig' list: 'SonataAdminBundle:CRUD:list.html.twig' show: 'SonataAdminBundle:CRUD:show.html.twig' show_compare: 'SonataAdminBundle:CRUD:show_compare.html.twig' edit: 'SonataAdminBundle:CRUD:edit.html.twig'
...
Sobrescribir templates
# app/config/config.yml
sonata_admin: templates: user_block: 'SonataAdminBundle:Core:user_block.html.twig' add_block: 'SonataAdminBundle:Core:add_block.html.twig' layout: 'SonataAdminBundle::standard_layout.html.twig' ajax: 'SonataAdminBundle::ajax_layout.html.twig' dashboard: 'SonataAdminBundle:Core:dashboard.html.twig' search: 'SonataAdminBundle:Core:search.html.twig' list: 'SonataAdminBundle:CRUD:list.html.twig' show: 'SonataAdminBundle:CRUD:show.html.twig' show_compare: 'SonataAdminBundle:CRUD:show_compare.html.twig' edit: 'AppBundle:Admin:edit.html.twig'
...
Sobrescribir templates
# app/config/config.yml
sonata_admin: templates: user_block: 'SonataAdminBundle:Core:user_block.html.twig' add_block: 'SonataAdminBundle:Core:add_block.html.twig' layout: 'SonataAdminBundle::standard_layout.html.twig' ajax: 'SonataAdminBundle::ajax_layout.html.twig' dashboard: 'SonataAdminBundle:Core:dashboard.html.twig' search: 'SonataAdminBundle:Core:search.html.twig' list: 'SonataAdminBundle:CRUD:list.html.twig' show: 'SonataAdminBundle:CRUD:show.html.twig' show_compare: 'SonataAdminBundle:CRUD:show_compare.html.twig' edit: 'AppBundle:Admin:edit.html.twig'
...
Fundamental buscar la template original y ver qué queremos sobrescribir exactamente
Sobrescribir templates
# vendor/sonata-project/admin-bundle/Resources/views/CRUD/edit.html.twig
{% extends 'SonataAdminBundle:CRUD:base_edit.html.twig' %}
Sobrescribir templates
# vendor/sonata-project/admin-bundle/Resources/views/CRUD/edit.html.twig
{% extends 'SonataAdminBundle:CRUD:base_edit.html.twig' %}
# vendor/sonata-project/admin-bundle/Resources/views/CRUD/base_edit.html.twig
{% block formactions %}...{% block formactions %}
Screenshots (III): Sobrescribir templates
Screenshots (III): Sobrescribir templates
¿Y si solo quiero sobrescribir la template de un Admin concreto?
Sobrescribir templates
# app/config/services.yml
services: admin.regalo: class: AppBundle\Admin\RegaloAdmin arguments: [~, AppBundle\Entity\Regalo, ~] tags: - { name: sonata.admin, manager_type: orm, label: Regalos }
Sobrescribir templates
# app/config/services.yml
services: admin.regalo: class: AppBundle\Admin\RegaloAdmin arguments: [~, AppBundle\Entity\Regalo, ~] tags: - { name: sonata.admin, manager_type: orm, label: Regalos } calls: - [ setTemplate, [edit, :Admin:edit_regalo.html.twig]]
Screenshots (III): Sobrescribir templates
¿Cómo sobrescribo la template de un campo concreto del listado?
Sobrescribir la template de un field en el list
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureListFields(ListMapper $listMapper) { $listMapper
...
; }
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'))
; }
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'))
; }
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 %}
Screenshots (III): Sobrescribir la template de un field en el list
Modificando las queries
Screenshots (III): Modificar la query del list
Modificar la query del list
# src/AppBundle/Admin/RegaloAdmin.php
public function createQuery($context = 'list') { $query = parent::createQuery($context); $rootAlias = $query->getRootAliases()[0]; $query ->andWhere( $query->expr()->eq($rootAlias.'.entregado', ':entregado')); $query->setParameter('entregado', false);
return $query; }
Modificar la query del list
# src/AppBundle/Admin/RegaloAdmin.php
public function createQuery($context = 'list') { $query = parent::createQuery($context); $rootAlias = $query->getRootAliases()[0]; $query ->andWhere( $query->expr()->eq($rootAlias.'.entregado', ':entregado')); $query->setParameter('entregado', false);
return $query; }
Screenshots (III): Modificar la query del list
Screenshots (III): Modificar la query de un filtro
Screenshots (III): Modificar la query de un filtro
Screenshots (III): Modificar la query de un filtro
Modificar la query de un filtro
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureDatagridFilters(DatagridMapper $datagridMapper) { $datagridMapper ->add('miFiltro', 'doctrine_orm_callback',array( 'callback' => function($queryBuilder, $alias, $field, $value) { if (!$value['value']) { return; }
$queryBuilder->andWhere($alias.'.estado != :estado'); $queryBuilder->setParameter('estado', 'entregado');
return true; }, 'field_type' => 'checkbox', 'label' => 'No entregados' )) ; }
Modificar la query de un filtro
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureDatagridFilters(DatagridMapper $datagridMapper) { $datagridMapper ->add('miFiltro', 'doctrine_orm_callback',array( 'callback' => function($queryBuilder, $alias, $field, $value) { if (!$value['value']) { return; }
$queryBuilder->andWhere($alias.'.estado != :estado'); $queryBuilder->setParameter('estado', 'entregado');
return true; }, 'field_type' => 'checkbox', 'label' => 'No entregados' )) ; }
Modificar la query de un filtro
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureDatagridFilters(DatagridMapper $datagridMapper) { $datagridMapper ->add('miFiltro', 'doctrine_orm_callback',array( 'callback' => function($queryBuilder, $alias, $field, $value) { if (!$value['value']) { return; }
$queryBuilder->andWhere($alias.'.estado != :estado'); $queryBuilder->setParameter('estado', 'entregado');
return true; }, 'field_type' => 'checkbox', 'label' => 'No entregados' )) ; }
Modificar la query de un filtro
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureDatagridFilters(DatagridMapper $datagridMapper) { $datagridMapper ->add('miFiltro', 'doctrine_orm_callback',array( 'callback' => function($queryBuilder, $alias, $field, $value) { if (!$value['value']) { return; }
$queryBuilder->andWhere($alias.'.estado != :estado'); $queryBuilder->setParameter('estado', 'entregado');
return true; }, 'field_type' => 'checkbox', 'label' => 'No entregados' )) ; }
Screenshots (III): Modificar la query de un filtro
Screenshots (III): Modificar la query de un filtro
Escribiendo en el controlador
Screenshots (III): Crear un action custom
Crear un action custom (paso 1)
# src/AppBundle/Controller/RegaloAdminController.php
use Sonata\AdminBundle\Controller\CRUDController as Controller;use Symfony\Component\HttpFoundation\RedirectResponse;
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')); }}
Crear un action custom (paso 1)
# src/AppBundle/Controller/RegaloAdminController.php
use Sonata\AdminBundle\Controller\CRUDController as Controller;use Symfony\Component\HttpFoundation\RedirectResponse;
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')); }}
Crear un action custom (paso 1)
# src/AppBundle/Controller/RegaloAdminController.php
use Sonata\AdminBundle\Controller\CRUDController as Controller;use Symfony\Component\HttpFoundation\RedirectResponse;
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')); }}
Crear un action custom (paso 2)
# app/config/services.yml
services: admin.regalo: class: AppBundle\Admin\RegaloAdmin arguments: [~, AppBundle\Entity\Regalo, ~] tags: - { name: sonata.admin, manager_type: orm, label: Regalos } calls: - [ setTemplate, [edit, :Admin:edit_regalo.html.twig]]
Crear un action custom (paso 2)
# app/config/services.yml
services: admin.regalo: class: AppBundle\Admin\RegaloAdmin arguments: [~, AppBundle\Entity\Regalo, AppBundle\RegaloAdmin] tags: - { name: sonata.admin, manager_type: orm, label: Regalos } calls: - [ setTemplate, [edit, :Admin:edit_regalo.html.twig]]
Crear un action custom (paso 3)
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureRoutes(RouteCollection $collection) { $collection->add('sendEmail', $this->getRouterIdParameter().'/send-email'); }
Crear un action custom (paso 3)
# src/AppBundle/Admin/RegaloAdmin.php
protected function configureRoutes(RouteCollection $collection) { $collection->add('sendEmail', $this->getRouterIdParameter().'/send-email'); }
Crear un action custom
# 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 %}
Crear un action custom
# 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="{{
admin.generateObjectUrl('sendEmail', object) }}"> <i class="fa fa-envelope"></i> Enviar
</a>{% endblock %}
Screenshots (III): Crear un action custom
Screenshots (III): Crear una batch action custom
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')); }
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')); }
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; }
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; }
Screenshots (III): Crear una batch action custom
IV. Consejos prácticos
O conjunto de ideas varias que pueden venir bien en cualquier proyecto
¿Cómo toco el aspecto general del panel?
Aspecto general
Aspecto general
Aspecto general
# app/config/config.yml
sonata_admin: title: deSymfony
Aspecto general
# app/config/config.yml
sonata_admin: title: deSymfony title_logo: 'img/logo.png'
Aspecto general
# app/config/config.yml
sonata_admin: title: deSymfony title_logo: 'img/logo.png' assets: stylesheets: - bundles/sonatacore/vendor/bootstrap/dist/css/bootstrap.min.css - bundles/sonatacore/vendor/ionicons/css/ionicons.min.css - bundles/sonataadmin/vendor/admin-lte/dist/css/AdminLTE.min.css - bundles/sonataadmin/vendor/admin-lte/dist/css/skins/skin-black.min.css - bundles/sonataadmin/vendor/iCheck/skins/square/blue.css - bundles/sonataadmin/vendor/jqueryui/themes/base/jquery-ui.css - bundles/sonatacore/vendor/select2/select2.css - bundles/sonataadmin/css/styles.css - bundles/sonataadmin/css/layout.css - bundles/sonataadmin/css/tree.css - bundles/sonataadmin/css/colors.css
…
Aspecto general
# app/config/config.yml
sonata_admin: title: deSymfony title_logo: 'img/logo.png' assets: stylesheets: - bundles/sonatacore/vendor/bootstrap/dist/css/bootstrap.min.css - bundles/sonatacore/vendor/ionicons/css/ionicons.min.css - bundles/sonataadmin/vendor/admin-lte/dist/css/AdminLTE.min.css - bundles/sonataadmin/vendor/admin-lte/dist/css/skins/skin-black.min.css - bundles/sonataadmin/vendor/iCheck/skins/square/blue.css - bundles/sonataadmin/vendor/jqueryui/themes/base/jquery-ui.css - bundles/sonatacore/vendor/select2/select2.css - bundles/sonataadmin/css/styles.css - bundles/sonataadmin/css/layout.css - bundles/sonataadmin/css/tree.css - bundles/sonataadmin/css/colors.css
…
https://sonata-project.org/bundles/admin/master/doc/reference/configuration.html
Aspecto general
# app/config/config.yml
sonata_admin: title: deSymfony title_logo: 'img/logo.png' assets: stylesheets: - bundles/sonatacore/vendor/bootstrap/dist/css/bootstrap.min.css - bundles/sonatacore/vendor/ionicons/css/ionicons.min.css - bundles/sonataadmin/vendor/admin-lte/dist/css/AdminLTE.min.css - bundles/sonataadmin/vendor/admin-lte/dist/css/skins/skin-black.min.css - bundles/sonataadmin/vendor/iCheck/skins/square/blue.css - bundles/sonataadmin/vendor/jqueryui/themes/base/jquery-ui.css - bundles/sonatacore/vendor/select2/select2.css - bundles/sonataadmin/css/styles.css - bundles/sonataadmin/css/layout.css - bundles/sonataadmin/css/tree.css - bundles/sonataadmin/css/colors.css - css/styles.css
…
Aspecto general
Aspecto general
# app/config/config.yml
sonata_admin: title: deSymfony title_logo: 'img/logo.png' assets: stylesheets: - bundles/sonatacore/vendor/bootstrap/dist/css/bootstrap.min.css - bundles/sonatacore/vendor/ionicons/css/ionicons.min.css - bundles/sonataadmin/vendor/admin-lte/dist/css/AdminLTE.min.css - bundles/sonataadmin/vendor/admin-lte/dist/css/skins/skin-black.min.css - bundles/sonataadmin/vendor/iCheck/skins/square/blue.css - bundles/sonataadmin/vendor/jqueryui/themes/base/jquery-ui.css - bundles/sonatacore/vendor/select2/select2.css - bundles/sonataadmin/css/styles.css - bundles/sonataadmin/css/layout.css - bundles/sonataadmin/css/tree.css - bundles/sonataadmin/css/colors.css - css/styles.css
…
Aspecto general
# app/config/config.yml
sonata_admin: title: deSymfony title_logo: 'img/logo.png' assets: stylesheets: - bundles/sonatacore/vendor/bootstrap/dist/css/bootstrap.min.css - bundles/sonatacore/vendor/ionicons/css/ionicons.min.css - bundles/sonataadmin/vendor/admin-lte/dist/css/AdminLTE.min.css - bundles/sonataadmin/vendor/admin-lte/dist/css/skins/skin-black.min.css - bundles/sonataadmin/vendor/iCheck/skins/square/blue.css - bundles/sonataadmin/vendor/jqueryui/themes/base/jquery-ui.css - bundles/sonatacore/vendor/select2/select2.css - bundles/sonataadmin/css/styles.css - bundles/sonataadmin/css/layout.css - bundles/sonataadmin/css/tree.css - bundles/sonataadmin/css/colors.css - css/styles.css
…
Aspecto general
# app/config/config.yml
sonata_admin: title: deSymfony title_logo: 'img/logo.png' assets: stylesheets: - bundles/sonatacore/vendor/bootstrap/dist/css/bootstrap.min.css - bundles/sonatacore/vendor/ionicons/css/ionicons.min.css - bundles/sonataadmin/vendor/admin-lte/dist/css/AdminLTE.min.css - bundles/sonataadmin/vendor/admin-lte/dist/css/skins/skin-black.min.css
…
https://almsaeedstudio.com/
Sonata utiliza AdminLTE, para lo visual generalmente hay que indagar allí
Aspecto general - Layout
Aspecto general - Layout
Aspecto general - Layout
Aspecto general - Layout
# app/config/config.yml
sonata_admin: templates: user_block: 'SonataAdminBundle:Core:user_block.html.twig' add_block: 'SonataAdminBundle:Core:add_block.html.twig' layout: 'SonataAdminBundle::standard_layout.html.twig' ajax: 'SonataAdminBundle::ajax_layout.html.twig' dashboard: 'SonataAdminBundle:Core:dashboard.html.twig' search: 'SonataAdminBundle:Core:search.html.twig' list: 'SonataAdminBundle:CRUD:list.html.twig' show: 'SonataAdminBundle:CRUD:show.html.twig' show_compare: 'SonataAdminBundle:CRUD:show_compare.html.twig' edit: 'SonataAdminBundle:CRUD:edit.html.twig'
...
Aspecto general - Layout
# app/config/config.yml
sonata_admin: templates: user_block: 'SonataAdminBundle:Core:user_block.html.twig' add_block: 'SonataAdminBundle:Core:add_block.html.twig' layout: 'SonataAdminBundle::standard_layout.html.twig' ajax: 'SonataAdminBundle::ajax_layout.html.twig' dashboard: 'SonataAdminBundle:Core:dashboard.html.twig' search: 'SonataAdminBundle:Core:search.html.twig' list: 'SonataAdminBundle:CRUD:list.html.twig' show: 'SonataAdminBundle:CRUD:show.html.twig' show_compare: 'SonataAdminBundle:CRUD:show_compare.html.twig' edit: 'SonataAdminBundle:CRUD:edit.html.twig'
...
Aspecto general - Layout
# app/config/config.yml
sonata_admin: templates: user_block: 'SonataAdminBundle:Core:user_block.html.twig' add_block: 'SonataAdminBundle:Core:add_block.html.twig' layout: ':Admin:layout.html.twig' ajax: 'SonataAdminBundle::ajax_layout.html.twig' dashboard: 'SonataAdminBundle:Core:dashboard.html.twig' search: 'SonataAdminBundle:Core:search.html.twig' list: 'SonataAdminBundle:CRUD:list.html.twig' show: 'SonataAdminBundle:CRUD:show.html.twig' show_compare: 'SonataAdminBundle:CRUD:show_compare.html.twig' edit: 'SonataAdminBundle:CRUD:edit.html.twig'
...
Aspecto general - Layout
Aspecto general - Dashboard
Aspecto general - Dashboard
# app/config/config.yml
sonata_admin: templates: user_block: 'SonataAdminBundle:Core:user_block.html.twig' add_block: 'SonataAdminBundle:Core:add_block.html.twig' layout: 'SonataAdminBundle::standard_layout.html.twig' ajax: 'SonataAdminBundle::ajax_layout.html.twig' dashboard: 'SonataAdminBundle:Core:dashboard.html.twig' search: 'SonataAdminBundle:Core:search.html.twig' list: 'SonataAdminBundle:CRUD:list.html.twig' show: 'SonataAdminBundle:CRUD:show.html.twig' show_compare: 'SonataAdminBundle:CRUD:show_compare.html.twig' edit: 'SonataAdminBundle:CRUD:edit.html.twig'
...
Aspecto general - Dashboard
# app/config/config.yml
sonata_admin: templates: user_block: 'SonataAdminBundle:Core:user_block.html.twig' add_block: 'SonataAdminBundle:Core:add_block.html.twig' layout: 'SonataAdminBundle::standard_layout.html.twig' ajax: 'SonataAdminBundle::ajax_layout.html.twig' dashboard: 'SonataAdminBundle:Core:dashboard.html.twig' search: 'SonataAdminBundle:Core:search.html.twig' list: 'SonataAdminBundle:CRUD:list.html.twig' show: 'SonataAdminBundle:CRUD:show.html.twig' show_compare: 'SonataAdminBundle:CRUD:show_compare.html.twig' edit: 'SonataAdminBundle:CRUD:edit.html.twig'
...
Aspecto general - Dashboard
# app/config/config.yml
sonata_admin: templates: user_block: 'SonataAdminBundle:Core:user_block.html.twig' add_block: 'SonataAdminBundle:Core:add_block.html.twig' layout: 'SonataAdminBundle::standard_layout.html.twig' ajax: 'SonataAdminBundle::ajax_layout.html.twig' dashboard: ':Admin:dashboard.html.twig' search: 'SonataAdminBundle:Core:search.html.twig' list: 'SonataAdminBundle:CRUD:list.html.twig' show: 'SonataAdminBundle:CRUD:show.html.twig' show_compare: 'SonataAdminBundle:CRUD:show_compare.html.twig' edit: 'SonataAdminBundle:CRUD:edit.html.twig'
...
Aspecto general - Dashboard
Aspecto general - Dashboard
Aspecto general - Dashboard
¿Puedo hacer dos admins de la misma entidad?
Crear dos admins de la misma entidad
# src/AppBundle/Admin/RegaloPasadoAdmin.php
class RegaloPasadoAdmin extends Admin
{
}
Sin problema. Creamos una nueva clase Admin…
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)
Crear dos admins de la misma entidad
# app/config/services.yml
services: admin.regalo: class: AppBundle\Admin\RegaloAdmin arguments: [~, AppBundle\Entity\Regalo, AppBundle:RegaloAdmin] tags: - { name: sonata.admin, manager_type: orm, label: Regalos } calls: - [ setTemplate, [edit, :Admin:edit_regalo.html.twig]]
… y registramos el nuevo servicio
Crear dos admins de la misma entidad
# app/config/services.yml
services: admin.regalo: class: AppBundle\Admin\RegaloAdmin arguments: [~, AppBundle\Entity\Regalo, AppBundle:RegaloAdmin] tags: - { name: sonata.admin, manager_type: orm, label: Activos } calls: - [ setTemplate, [edit, :Admin:edit_regalo.html.twig]] admin.regalo_pasado: class: AppBundle\Admin\RegaloPasadoAdmin arguments: [~, AppBundle\Entity\Regalo, ~] tags: - { name: sonata.admin, manager_type: orm, label: Pasados }
… y registramos el nuevo servicio
Crear dos admins de la misma entidad
Crear dos admins de la misma entidad
Crear dos admins de la misma entidad
Admin como child en el menú de otro Admin
Admin como child en el menú de otro Admin
Admin como child en el menú de otro Admin
Admin como child en el menú de otro Admin
# app/config/services.yml
admin.comprador: class: AppBundle\Admin\CompradorAdmin arguments: [~, AppBundle\Entity\Comprador, ~] tags: - { name: sonata.admin, manager_type: orm, label: Compradores } calls: - [ addChild, [ '@admin.pago' ] ] admin.pago: class: AppBundle\Admin\PagoAdmin arguments: [~, AppBundle\Entity\Pago, ~] tags: - { name: sonata.admin, manager_type: orm, label: Pagos }
Admin como child en el menú de otro Admin
# app/config/services.yml
admin.comprador: class: AppBundle\Admin\CompradorAdmin arguments: [~, AppBundle\Entity\Comprador, ~] tags: - { name: sonata.admin, manager_type: orm, label: Compradores } calls: - [ addChild, [ '@admin.pago' ] ] admin.pago: class: AppBundle\Admin\PagoAdmin arguments: [~, AppBundle\Entity\Pago, ~] tags: - { name: sonata.admin, manager_type: orm, label: Pagos }
Admin como child en el menú de otro Admin
# app/config/services.yml
admin.comprador: class: AppBundle\Admin\CompradorAdmin arguments: [~, AppBundle\Entity\Comprador, ~] tags: - { name: sonata.admin, manager_type: orm, label: Compradores } calls: - [ addChild, [ '@admin.pago' ] ] admin.pago: class: AppBundle\Admin\PagoAdmin arguments: [~, AppBundle\Entity\Pago, ~] tags: - { name: sonata.admin, manager_type: orm, label: Pagos }
Admin como child en el menú de otro Admin
# app/config/config.yml
admin.comprador: class: AppBundle\Admin\CompradorAdmin arguments: [~, AppBundle\Entity\Comprador, ~] tags: - { name: sonata.admin, manager_type: orm, label: Compradores } calls: - [ addChild, [ '@admin.pago' ] ] admin.pago: class: AppBundle\Admin\PagoAdmin arguments: [~, AppBundle\Entity\Pago, ~] tags: - { name: sonata.admin, manager_type: orm, label: Pagos }
Admin como child en el menú de otro Admin
# src/AppBundle/Admin/CompradorAdmin.php
protected function configureSideMenu(ItemInterface $menu, $action, AdminInterface $childAdmin = null) {
... $menu->addChild( 'Pagos', $admin->generateMenuUrl('admin.comprador|admin.pago.list', array('id' => $id)) ); }
Admin como child en el menú de otro Admin
# src/AppBundle/Admin/CompradorAdmin.php
protected function configureSideMenu(ItemInterface $menu, $action, AdminInterface $childAdmin = null) {
... $menu->addChild( 'Pagos', $admin->generateMenuUrl('admin.comprador|admin.pago.list', array('id' => $id)) ); }
Admin como child en el menú de otro Admin
¿Qué pasa si el listado no es lo principal?
Enlazar un action custom desde la sidebar
Creamos nuestro action custom, la template y la ruta...
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
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
Enlazar un action custom desde la sidebar
¿Y si quiero meter algo que no sea un Admin?
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
Toda tu aplicación puede estar dentro de Sonata
Toda tu aplicación puede estar dentro de Sonata
Toda tu aplicación puede estar dentro de Sonata
Creas tu action en el controlador (PacienteAdminController.php)
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');
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>
V. Más allá
O qué otras cosas hay ahí fuera y dónde puedo encontrarlas
Documentación de SonataAdminBundle
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
Seguridad, roles
https://sonata-project.org/bundles/admin/3-x/doc/reference/security.html
La seguridad se puede configurar de muchas formas distintas y con tanto detalle como quieras
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
Sonata Project Demo
Sonata Project Demo
Sonata Project Demo
Y a la hora de la verdad.. pues el código
Admin class
Conviene mucho mirarse la Admin class
vendor/sonata-project/admin-bundle/Admin/AbstractAdmin.php
VI. Conclusiones
O con qué me quedo de todo esto
Conclusiones
● Los principales problemas se han ido solucionando. Y sigue mejorando.
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.
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.
Conclusiones
Te permite solucionar un problema aburrido de una forma eficiente
Conclusiones
Te permite solucionar un problema aburrido de una forma eficiente
Para que puedas dedicarte a otra cosa más emocionante
Conclusiones
Y desde el punto de vista del negocio suele ser muy buena decisión
Victoria Quirante Ruiz Madrid, 16-17 Sep. 2016#deSymfony
https://github.com/VictoriaQ/sonatademo
Formación, consultoría y desarrollo de proyectos
Victoria Quirante Ruiz Madrid, 16-17 Sep. 2016#deSymfony
https://github.com/VictoriaQ/sonatademo
Formación, consultoría y desarrollo de proyectos
Gracias!