EASYADMIN EN SYMFONY: TUTORIAL PARA CREAR UN PANEL DE ADMINISTRACIÓN
Actualmente estoy usando el bundle easyadmin de symfony y la verdad es que es bastante sencillo, ya que con un fichero de configuración, en formato yaml, es suficiente. Aunque se pueden hacer administradores más complejos y progrmando en php y symfony. Y aunque hay bastante documentación, y ejemplos, en internet creo que con este tutorial easyadmin de symfony intentaré cubrir bastantes necesidades cuando se quiere hacer un admin algo más complejo. Por ejemplo usar varios controladores de symfony cuando el admin va a ser muy amplio y se quiere dividir la programaci?on popr entidades, por ejemplo. Yo lo estoy usando con symfony 5.Una vez instalado el bundle voy a explicar las diferentes partes por separado:
Primero nos dispondremos a abrir el fichero routes.yaml y añadiremos lo siguiente:
easy_admin_bundle:
resource: '@EasyAdminBundle/Controller/EasyAdminController.php'
prefix: /admin
type: annotation
namespace App\Controller;
use Doctrine\ORM\EntityManagerInterface;
use EasyCorp\Bundle\EasyAdminBundle\Controller\EasyAdminController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
class AdminController extends EasyAdminController
{
protected $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
/**
* @Route("/", name="easyadmin")
*/
public function indexAction(Request $request)
{
return parent::indexAction($request);
}
}
Luego abriremos el fichero easy_admin.yaml que se encuentra en "config/packages". Donde se añadirá toda la configuración y es la parte más importante del easyadmin
easy_admin:
site_name: 'My Admin'
design:
menu: [{ entity: 'Provider', label: 'Data Providers' },
{ entity: 'Product', label: 'Credit Cards' }]
formats:
date: 'd/m/Y'
entities:
Provider:
class: App\Entity\Provider
controller: App\Controller\Admin\AdminProviderController
label: Data Providers
list:
sort: ['id', 'DESC']
disabled_actions: ['delete']
actions:
- { name: 'editProvider', type: 'route', label: 'Edit' }
fields:
- { property: 'name', label: 'Name' }
- { property: 'affiliation', label: 'Type' }
form:
fields:
- { property: 'name',type_options: { required: true } }
- { property: 'affiliation', label: 'Type', type: 'choice',type_options:{choices: { 'Affiliate': 'affiliate', 'Direct': 'direct' }}}
- { property: 'ws_url', type: 'text',type_options: { required: true } }
- { property: 'ws_url_stats', type: 'text',type_options: { required: true } }
- { property: 'data_type', type: 'text',type_options: { required: true } }
- { property: 'api_user', type: 'text'}
- { property: 'api_key', type: 'text',type_options: { required: true } }
- { property: 'slug', type: 'text'}
Product:
class: App\Entity\Product
controller: App\Controller\Admin\AdminProductController
label: Credit Cards
disabled_actions: ['delete']
form:
fields:
- { property: 'name'}
- { property: 'provider', label: 'Data provider'}
- { property: 'link', label: 'Deep link', type: 'text',type_options: { required: true } }
- { property: 'final_url', type: 'text',type_options: { required: true } }
- { property: 'provider_reference', type: 'hidden',type_options: { data: '0' } }
- { property: 'visible', type: 'hidden',type_options: { data: '0' } }
list:
actions:
- { name: 'edit', label: '' }
fields:
- { property: 'name', label: 'Name' }
- { property: 'Provider.name', label: 'Data provider' }
- { property: 'visible', label: 'Visible in Web', type: 'toggle' }
- design: Como el propio nombre indica es la sección de diseño. Está definido el menú lateral que entidades se van a usar en el admin y el nombre que se va a mostrar en el menú
- entities: Por cada entity definida en el apartado anterior se puede configurar que campos apareceran en el listado principal, el formulario de creación y edición, se pueden definir juntos o por separado y el controller que se va a usar.
- class: Ruta a la entity, pero la ruta por namespace no ruta física. Este campo es obligatorio"
- controller: Ruta al controlador, pero la ruta por namespace no ruta física. Este campo es opcional. Se suele usar por si se quiere hacer un override de alguna función como el listado, creación o edición. En el caso de "provider" no hace falta pero para "product" sí.
- list: Se definen los que campos se van a mostrar en el listado. Los campos son los atributos de la entity. En el ejmplo anterior tenemos dos entities "Provider" y "Product" si os mostrase las dos entities veríais que tiene esos mismos atributos que son los campos de la tabla de la base de datos.
- form: Se definen los que campos se van a añadir en el formulario de creación edición, aunque se puede definir por separado. Los campos son los atributos de la entity. En el código anterior tenemos dos entities "Provider" y "Product" si os mostrase las dos entities veríais que tiene esos mismos atributos que son los campos de la tabla de la base de datos. Si queremos definir un campo de tipo "file" en la sección de form se le puede indicar el nombre del archivo y la ruta. En este caso la ruta está definida en una variable de entorno, sino se especifica la ruta los archivos se subirán a "public/uploads/files/" y el nombre del archivo está formado por timestamp y un randhomhash y guardando la imagen con su propia extensión:
" - { property: 'logo', type: 'file_upload', type_options: { upload_dir: '%env(PATH_UPLOAD_IMAGES_TMP)%', upload_filename: '[timestamp][randomhash].[extension]'}}" - actions: Se refiere a las acciones que se pueden hacer por cada dato en el listado. Las disponibles son "edit" y "delete"
- disabled actions: Se refiere a las acciones desabilitadas. Las disponibles son "new", "edit" y "delete". Como se puede ver en la entidad "Product:" se ha deshabilitado la acci?on "delete", por ponerlo de ejemplo en list, en la subsección de action aparece que edit tiene la opción de edit con una cadena vacía y en la subsección de fields aparece que el campo visible tiene el tipo toggle ya que desde el listado se muestra un togle para poder marcar el producto como visible o no en la web y si se deshabilita la opción edit no funcionaría. Por eso está hecho así.
Cuando necesitaemos que la acción de listado o creación tenga una funcionalidad específica se hace de forma diferente. Lo que hay que hacer es crear una función, en el controlador definido en la sección "controller" y llamarla de las siguientes formas:
- Para el listado sería "protected function listEntityAction()". Por ejemplo para la sección provider sería: "protected function listProviderAction()"
- Para la creación sería "protected function newEntityAction()()". Por ejemplo para la sección producto sería: "protected function newProductAction()()"