SlideShare uma empresa Scribd logo
1 de 133
Baixar para ler offline
SensioLabs
SYMFONY
BUENAS PRÁCTICAS
Javier Eguiluz
Symfony
Barcelona
gracias a
Marc Morera
@mmoreram
gracias a
Elcodi
Symfony components based
e-commerce platform
gracias a
Introducción
13
OCTUBRE
Las buenas prácticas oficiales
Conjunto de técnicas que
puedes utilizar para desarrollar
aplicaciones Symfony como
recomiendan sus creadores.
symfony.com/best-practices
LIBROSWEB
FABIEN POTENCIER
RYAN WEAVER
JAVIER EGUILUZ
BUENAS
PRÁCTICAS
PARA APLICACIONES
SYMFONY
bit.ly/buenas-practicas-symfony
50
páginas
57
páginas
¿Por qué?
Las buenas prácticas oficiosas
complican mucho el desarrollo
de aplicaciones y no siguen la
filosofía pragmática de los
creadores de Symfony.
Definición de “Best Practice”
A well defined procedure
that is known to produce
near-optimum results.
Definición de “Pragmatic”
Concerned with making
decisions and actions that
are useful in practice, not
just theory.
Las buenas prácticas Symfony
Las buenas prácticas Symfony
• Reflejan las ideas de su creador.
Las buenas prácticas Symfony
• Reflejan las ideas de su creador.
• Son opcionales.
Las buenas prácticas Symfony
• Reflejan las ideas de su creador.
• Son opcionales.
• Symfony no cambiará para
obligarte a usarlas.
Usa las buenas prácticas …
Usa las buenas prácticas …
• En proyectos pequeños y medianos.
Usa las buenas prácticas …
• En proyectos pequeños y medianos.
• En proyectos web estándar.
Usa las buenas prácticas …
• En proyectos pequeños y medianos.
• En proyectos web estándar.
• Si eres nuevo/a en Symfony.
No uses las buenas prácticas …
No uses las buenas prácticas …
• En bundles compartidos (públicos o
privados).
No uses las buenas prácticas …
• En bundles compartidos (públicos o
privados).
• En aplicaciones muy complejas o con
arquitecturas muy especiales.
No uses las buenas prácticas …
• En bundles compartidos (públicos o
privados).
• En aplicaciones muy complejas o con
arquitecturas muy especiales.
• Si tienes tus propias buenas prácticas.
Aplicaciones vs
bundles
Estructura de una aplicación web
proyecto/
!" app/
# !" config/
# $" Resources/
# $" views/
!" src/
!" vendor/
$" web/
!" css/
$" js/
Estructura de una aplicación web
configuración
proyecto/
!" app/
# !" config/
# $" Resources/
# $" views/
!" src/
!" vendor/
$" web/
!" css/
$" js/
Estructura de una aplicación web
configuración
plantillas
proyecto/
!" app/
# !" config/
# $" Resources/
# $" views/
!" src/
!" vendor/
$" web/
!" css/
$" js/
Estructura de una aplicación web
configuración
plantillas
tu código
proyecto/
!" app/
# !" config/
# $" Resources/
# $" views/
!" src/
!" vendor/
$" web/
!" css/
$" js/
Estructura de una aplicación web
configuración
plantillas
tu código
dependencias
proyecto/
!" app/
# !" config/
# $" Resources/
# $" views/
!" src/
!" vendor/
$" web/
!" css/
$" js/
Estructura de una aplicación web
configuración
plantillas
tu código
dependencias
assets
proyecto/
!" app/
# !" config/
# $" Resources/
# $" views/
!" src/
!" vendor/
$" web/
!" css/
$" js/
¿Cómo crear un sistema de plugins?
¿Cómo crear un sistema de plugins?
• Deben funcionar de manera
autónoma.
¿Cómo crear un sistema de plugins?
• Deben funcionar de manera
autónoma.
• Pueden definir su propia
configuración.
¿Cómo crear un sistema de plugins?
• Deben funcionar de manera
autónoma.
• Pueden definir su propia
configuración.
• Pueden incluir plantillas y assets.
Estructura de un plugin
plugin/
!" DependencyInjection/
# $" Configuration.php
!" Resources/
# !" config/
# !" public/
# # !" css/
# # $" js/
# $" views/
$" ...
Estructura de un plugin
configuración
plugin/
!" DependencyInjection/
# $" Configuration.php
!" Resources/
# !" config/
# !" public/
# # !" css/
# # $" js/
# $" views/
$" ...
Estructura de un plugin
configuración
assets
plugin/
!" DependencyInjection/
# $" Configuration.php
!" Resources/
# !" config/
# !" public/
# # !" css/
# # $" js/
# $" views/
$" ...
Estructura de un plugin
configuración
plantillas
assets
plugin/
!" DependencyInjection/
# $" Configuration.php
!" Resources/
# !" config/
# !" public/
# # !" css/
# # $" js/
# $" views/
$" ...
Estructura de un plugin
configuración
plantillas
tu código
assets
plugin/
!" DependencyInjection/
# $" Configuration.php
!" Resources/
# !" config/
# !" public/
# # !" css/
# # $" js/
# $" views/
$" ...
proyecto/
!" app/
# !" config/
# $" Resources/
# $" views/
!" src/
!" vendor/
$" web/
!" css/
$" js/
Aplicaciones vs plugins/bundles
bundle/
!" DependencyInjection/
# $" Configuration.php
!" Resources/
# !" config/
# !" public/
# # !" css/
# # $" js/
# $" views/
$" ...
Los bundles son mini-aplicaciones
Configuración Plantillas
Código!
fuente
Assets
Contenedor
servicios
Kernel
Caché!
y logs
Aplicación ✔ ✔ ✔ ✔ ✔ ✔ ✔
Bundle ✔ ✔ ✔ ✔ ✔ ✘ ✘
proyecto/
!" app/
# !" config/
# $" Resources/
# $" views/
!" src/
#
#
#
#
#
#
!" vendor/
$" web/
!" css/
$" js/
Los bundles en aplicaciones privadas
AcmeUserBundle/
!" DependencyInjection/
# $" Configuration.php
!" Resources/
# !" config/
# !" public/
# # !" css/
# # $" js/
# $" views/
$" ...
AcmeProductBundle/
!" DependencyInjection/
# $" Configuration.php
!" Resources/
# !" config/
# !" public/
# # !" css/
# # $" js/
# $" views/
$" ...
AcmeOfferBundle/
!" DependencyInjection/
# $" Configuration.php
!" Resources/
# !" config/
# !" public/
# # !" css/
# # $" js/
# $" views/
$" ...
AcmeInvoiceBundle/
!" DependencyInjection/
# $" Configuration.php
!" Resources/
# !" config/
# !" public/
# # !" css/
# # $" js/
# $" views/
$" ...
proyecto/
!" app/
# !" config/
# $" Resources/
# $" views/
!" src/
#
#
#
#
#
#
!" vendor/
$" web/
!" css/
$" js/
Los bundles en aplicaciones privadas
AcmeUserBundle/
!" DependencyInjection/
# $" Configuration.php
!" Resources/
# !" config/
# !" public/
# # !" css/
# # $" js/
# $" views/
$" ...
AcmeProductBundle/
!" DependencyInjection/
# $" Configuration.php
!" Resources/
# !" config/
# !" public/
# # !" css/
# # $" js/
# $" views/
$" ...
AcmeOfferBundle/
!" DependencyInjection/
# $" Configuration.php
!" Resources/
# !" config/
# !" public/
# # !" css/
# # $" js/
# $" views/
$" ...
AcmeInvoiceBundle/
!" DependencyInjection/
# $" Configuration.php
!" Resources/
# !" config/
# !" public/
# # !" css/
# # $" js/
# $" views/
$" ...
proyecto/
!" app/
# !" config/
# $" Resources/
# $" views/
!" src/
#
#
#
#
#
#
!" vendor/
$" web/
!" css/
$" js/
Los bundles en aplicaciones privadas
AcmeUserBundle/
!" DependencyInjection/
# $" Configuration.php
!" Resources/
# !" config/
# !" public/
# # !" css/
# # $" js/
# $" views/
$" ...
AcmeProductBundle/
!" DependencyInjection/
# $" Configuration.php
!" Resources/
# !" config/
# !" public/
# # !" css/
# # $" js/
# $" views/
$" ...
AcmeOfferBundle/
!" DependencyInjection/
# $" Configuration.php
!" Resources/
# !" config/
# !" public/
# # !" css/
# # $" js/
# $" views/
$" ...
AcmeInvoiceBundle/
!" DependencyInjection/
# $" Configuration.php
!" Resources/
# !" config/
# !" public/
# # !" css/
# # $" js/
# $" views/
$" ...
Una verdad incómoda
Es muy probable que los
bundles de tus aplicaciones
no sean bundles, sólo
directorios que molestan.
Buenas prácticas en
la práctica
Organizando el
proyecto
Seguridad
Anotaciones
Simplificaciones
Organizando el
proyecto
Seguridad
Anotaciones
Simplificaciones
Crea un solo
bundle llamado
AppBundle
aplicacion/
!" app/
!" src/
# !" ContactBundle/
# # $" Controller/
# # $" DefaultController.php
# !" PaymentBundle/
# # $" Controller/
# # $" DefaultController.php
# !" ProductBundle/
# # $" Controller/
# # $" DefaultController.php
# $" UserBundle/
# $" Controller/
# $" DefaultController.php
!" vendor/
$" web/
aplicacion/
!" app/
!" src/
# $" AppBundle/
# $" Controller/
# !" ContactController.php
# !" PaymentController.php
# !" ProductController.php
# $" UserController.php
!" vendor/
$" web/
Aplicaciones Symfony tradicionales Buenas Prácticas oficiales
aplicacion/
!" app/
!" src/
# !" ContactBundle/
# # $" Controller/
# # $" DefaultController.php
# !" PaymentBundle/
# # $" Controller/
# # $" DefaultController.php
# !" ProductBundle/
# # $" Controller/
# # $" DefaultController.php
# $" UserBundle/
# $" Controller/
# $" DefaultController.php
!" vendor/
$" web/
aplicacion/
!" app/
!" src/
# $" AppBundle/
# $" Controller/
# !" ContactController.php
# !" PaymentController.php
# !" ProductController.php
# $" UserController.php
!" vendor/
$" web/
Aplicaciones Symfony tradicionales Buenas Prácticas oficiales
8directorios
4archivos
aplicacion/
!" app/
!" src/
# !" ContactBundle/
# # $" Controller/
# # $" DefaultController.php
# !" PaymentBundle/
# # $" Controller/
# # $" DefaultController.php
# !" ProductBundle/
# # $" Controller/
# # $" DefaultController.php
# $" UserBundle/
# $" Controller/
# $" DefaultController.php
!" vendor/
$" web/
aplicacion/
!" app/
!" src/
# $" AppBundle/
# $" Controller/
# !" ContactController.php
# !" PaymentController.php
# !" ProductController.php
# $" UserController.php
!" vendor/
$" web/
Aplicaciones Symfony tradicionales Buenas Prácticas oficiales
8directorios
4archivos
2directorios
4archivos
aplicacion/
!" app/
!" src/
# !" ContactBundle/
# # $" Controller/
# # $" DefaultController.php
# !" PaymentBundle/
# # $" Controller/
# # $" DefaultController.php
# !" ProductBundle/
# # $" Controller/
# # $" DefaultController.php
# $" UserBundle/
# $" Controller/
# $" DefaultController.php
!" vendor/
$" web/
aplicacion/
!" app/
!" src/
# $" AppBundle/
# $" Controller/
# !" ContactController.php
# !" PaymentController.php
# !" ProductController.php
# $" UserController.php
!" vendor/
$" web/
Aplicaciones Symfony tradicionales Buenas Prácticas oficiales
aplicacion/
!" app/
!" src/
# !" ContactBundle/
# # $" Controller/
# # $" DefaultController.php
# !" PaymentBundle/
# # $" Controller/
# # $" DefaultController.php
# !" ProductBundle/
# # $" Controller/
# # $" DefaultController.php
# $" UserBundle/
# $" Controller/
| !" GroupController.php
| !" ProfileController.php
| !" RegistrationController.php
| !" ResettingController.php
| $" SecurityController.php
!" vendor/
$" web/
aplicacion/
!" app/
!" src/
# $" AppBundle/
# $" Controller/
# !" ContactController.php
# !" PaymentController.php
# !" ProductController.php
# $" User/
| !" GroupController.php
| !" ProfileController.php
| !" RegistrationController.php
| !" ResettingController.php
| $" SecurityController.php
!" vendor/
$" web/
Aplicaciones Symfony tradicionales Buenas Prácticas oficiales
aplicacion/
!" app/
!" src/
# !" ContactBundle/
# # $" Controller/
# # $" DefaultController.php
# !" PaymentBundle/
# # $" Controller/
# # $" DefaultController.php
# !" ProductBundle/
# # $" Controller/
# # $" DefaultController.php
# $" UserBundle/
# $" Controller/
| !" GroupController.php
| !" ProfileController.php
| !" RegistrationController.php
| !" ResettingController.php
| $" SecurityController.php
!" vendor/
$" web/
aplicacion/
!" app/
!" src/
# $" AppBundle/
# $" Controller/
# !" ContactController.php
# !" PaymentController.php
# !" ProductController.php
# $" User/
| !" GroupController.php
| !" ProfileController.php
| !" RegistrationController.php
| !" ResettingController.php
| $" SecurityController.php
!" vendor/
$" web/
Aplicaciones Symfony tradicionales Buenas Prácticas oficiales
8directorios
8archivos
aplicacion/
!" app/
!" src/
# !" ContactBundle/
# # $" Controller/
# # $" DefaultController.php
# !" PaymentBundle/
# # $" Controller/
# # $" DefaultController.php
# !" ProductBundle/
# # $" Controller/
# # $" DefaultController.php
# $" UserBundle/
# $" Controller/
| !" GroupController.php
| !" ProfileController.php
| !" RegistrationController.php
| !" ResettingController.php
| $" SecurityController.php
!" vendor/
$" web/
aplicacion/
!" app/
!" src/
# $" AppBundle/
# $" Controller/
# !" ContactController.php
# !" PaymentController.php
# !" ProductController.php
# $" User/
| !" GroupController.php
| !" ProfileController.php
| !" RegistrationController.php
| !" ResettingController.php
| $" SecurityController.php
!" vendor/
$" web/
Aplicaciones Symfony tradicionales Buenas Prácticas oficiales
8directorios
8archivos
3directorios
8archivos
Configuración del enrutamiento
# app/config/routing.yml
app:
resource: @AppBundle/Controller/
type: annotation
No añadas un
vendor en los
bundles que no
compartas
No añadas un vendor a los bundles privados
AcmeNetworksAcmeWebsiteMarketingBundle
!
AcmeNetworksAcmeWebsiteMarketingBundle:Default:index.html.twig
!
{{ render(controller(
'AcmeNetworksAcmeWebsiteMarketingBundle:Default:latestNews'
)) }}
No añadas un vendor a los bundles privados
AcmeNetworksAcmeWebsiteMarketingBundle
!
AcmeNetworksAcmeWebsiteMarketingBundle:Default:index.html.twig
!
{{ render(controller(
'AcmeNetworksAcmeWebsiteMarketingBundle:Default:latestNews'
)) }}
Esto lo he visto con
mis propios ojos
Guarda todas
tus plantillas
en app/
Esta buena práctica es
la que produce un
mayor impacto positivo
AVISO IMPORTANTE
aplicacion/
!" app/
!" src/
# !" ContactBundle/
# # $" Resources/
# # $" views/
# # $" Default/
# # !" index.html.twig
# # $" show.html.twig
# . . .
# $" ProductBundle/
# $" Resources/
# $" views/
# $" Default/
# !" index.html.twig
# !" category.html.twig
# $" show.html.twig
!" vendor/
$" web/
your-application/
!" app/
# $" Resources/
# $" views/
# !" contact/
# # !" index.html.twig
# # $" show.html.twig
# . . .
# $" product/
# !" index.html.twig
# !" category.html.twig
# $" show.html.twig
!" vendor/
$" web/
Aplicaciones Symfony tradicionales Buenas Prácticas oficiales
aplicacion/
!" app/
!" src/
# !" ContactBundle/
# # $" Resources/
# # $" views/
# # $" Default/
# # !" index.html.twig
# # $" show.html.twig
# . . .
# $" ProductBundle/
# $" Resources/
# $" views/
# $" Default/
# !" index.html.twig
# !" category.html.twig
# $" show.html.twig
!" vendor/
$" web/
your-application/
!" app/
# $" Resources/
# $" views/
# !" contact/
# # !" index.html.twig
# # $" show.html.twig
# . . .
# $" product/
# !" index.html.twig
# !" category.html.twig
# $" show.html.twig
!" vendor/
$" web/
Aplicaciones Symfony tradicionales Buenas Prácticas oficiales
8directorios
5archivos
aplicacion/
!" app/
!" src/
# !" ContactBundle/
# # $" Resources/
# # $" views/
# # $" Default/
# # !" index.html.twig
# # $" show.html.twig
# . . .
# $" ProductBundle/
# $" Resources/
# $" views/
# $" Default/
# !" index.html.twig
# !" category.html.twig
# $" show.html.twig
!" vendor/
$" web/
your-application/
!" app/
# $" Resources/
# $" views/
# !" contact/
# # !" index.html.twig
# # $" show.html.twig
# . . .
# $" product/
# !" index.html.twig
# !" category.html.twig
# $" show.html.twig
!" vendor/
$" web/
Aplicaciones Symfony tradicionales Buenas Prácticas oficiales
8directorios
5archivos
4directorios
5archivos
Centralizar las plantillas
Centralizar las plantillas
Cambia la vida
a tus diseñadores/as
Centralizar las plantillas
Cambia la vida
a tus diseñadores/as
Simplifica
mucho tu código
Nueva organización de plantillas
aplicacion/
$" app/Resources/views/
!" contact/
# !" index.html.twig
# $" show.html.twig
. . .
!
$" product/
!" index.html.twig
!" category.html.twig
$" show.html.twig
La nueva notación de las plantillas
$this->render('AcmeDemoBunde:Default:index.html.twig');
$this->render('default/index.html.twig');
!
$this->render('AcmeDemoBundle::index.html.twig');
$this->render('index.html.twig');
La nueva notación de las plantillas
{% extends '::layout.html.twig' %}
{% extends 'layout.html.twig' %}
!
{{ include('AcmeDemoBundle:Default:subdir/index.html.twig') }}
{{ include('default/subdir/index.html.twig') }}
!
{{ include('AcmeDemoBundle:Default/subdir:index.html.twig') }}
{{ include('default/subdir/index.html.twig') }}
Los problemas de la notación tradicional
AcmeDemoBundle:Default:subdir/index.html.twig
Los problemas de la notación tradicional
• Requiere explicársela a cada diseñador/programador.
AcmeDemoBundle:Default:subdir/index.html.twig
Los problemas de la notación tradicional
• Requiere explicársela a cada diseñador/programador.
• Tiene excepciones (alguna de sus partes puede estar
vacía) e inconsistencias (subdirectorios).
AcmeDemoBundle:Default:subdir/index.html.twig
Los problemas de la notación tradicional
• Requiere explicársela a cada diseñador/programador.
• Tiene excepciones (alguna de sus partes puede estar
vacía) e inconsistencias (subdirectorios).
• No es inmediato saber dónde está la plantilla (debes
traducir la notación a un directorio).
AcmeDemoBundle:Default:subdir/index.html.twig
Guarda todos
tus assets en
web/
Centralizar los assets (CSS, JavaScript)
• Tiene las mismas ventajas que centralizar
las plantillas.
Organizando los assets web
proyecto/
!" app/
!" src/
!" vendor/
$" web/
!" css/
# !" bootstrap.min.css
# $" app.css
$" js/
!" jquery.min.js
$" app.js
Organizando los assets web
proyecto/
!" app/
!" src/
!" vendor/
$" web/
!" css/
# !" bootstrap.min.css
# $" app.css
$" js/
!" jquery.min.js
$" app.js
proyecto/
!" app/
# $" Resources/
# $" assets/
# !" scss/
# # !" bootstrap/
# # $" app.scss
# $" js/
!" src/
!" vendor/
$" web/
!" css/app.css
$" js/app.js
En resumen
• Si utilizas mal los bundles, estás repitiendo
la estructura de la aplicación sin necesidad
• Si no vas a compartir tus bundles, utiliza
los directorios de la aplicación (app/
Resources/ y web/).
• El número de archivos se mantiene, los
directorios y la complejidad se reducen.
Organizando el
proyecto
Seguridad
Anotaciones
Simplificaciones
Escala de sensibilidad
para programadores
Escala de sensibilidad
para programadores
Política
Religión
Fútbol
Estándar de código
Editor de código
Anotaciones
Anotaciones PHP
use AppBundleEntityPost;
use SensioBundleFrameworkExtraBundleConfigurationRoute;
!
class CommentController extends Controller
{
/**
* @Route("/edit/{id}", name = "post_edit")
*/
public function editAction(Post $post)
{ ... }
!
/*
* @Route("/edit/{id}", name = "post_edit")
*/
public function editAction(Post $post)
{ ... }
}
Anotaciones PHP
use AppBundleEntityPost;
use SensioBundleFrameworkExtraBundleConfigurationRoute;
!
class CommentController extends Controller
{
/**
* @Route("/edit/{id}", name = "post_edit")
*/
public function editAction(Post $post)
{ ... }
!
/*
* @Route("/edit/{id}", name = "post_edit")
*/
public function editAction(Post $post)
{ ... }
}
Anotación
Anotaciones PHP
use AppBundleEntityPost;
use SensioBundleFrameworkExtraBundleConfigurationRoute;
!
class CommentController extends Controller
{
/**
* @Route("/edit/{id}", name = "post_edit")
*/
public function editAction(Post $post)
{ ... }
!
/*
* @Route("/edit/{id}", name = "post_edit")
*/
public function editAction(Post $post)
{ ... }
}
Anotación
Comentario
Anotaciones PHP
/** @Route(...) */Anotación
Comentario /* @Route(...) */
Utiliza @Route,
@Security y
@Cache
Enrutamiento tradicional
# app/config/routing.yml
_admin_post:
resource: '@AcmeAdminBundle/Resources/config/routing/post.yml'
prefix: '/admin/post'
!
# src/Acme/AdminBundle/Resources/config/routing/post.yml
admin_post_show:
pattern: '/{id}'
defaults: { _controller: 'AcmeAdminBundle:Post:show' }
!
!
namespace AcmeAdminBundleController;
!
class PostController {
public function showAction($id) { ... }
}
Enrutamiento con anotaciones
namespace AppBundleControllerAdmin;
!
use SymfonyBundleFrameworkBundleControllerController;
use SensioBundleFrameworkExtraBundleConfigurationRoute;
!
/**
* @Route("/admin/post")
*/
class PostController extends Controller
{
/**
* @Route("/{id}", name="admin_post_show")
*/
public function showAction($id) { ... }
}
No utilices la
anotación
@Template
La anotación @Template es mágica
/** @Template() */
public function indexAction()
{
// ...
return array('posts' => $posts);
}
!
!
public function indexAction()
{
// ...
return $this->render('blog/index.html.twig', array(
'posts' => $posts
));
}
Utiliza los
ParamConverter
cuando sea
sencillo
Los ParamConvertes en la práctica
use SensioBundleFrameworkExtraBundleConfigurationRoute;
use AppBundleEntityPost;
!
class CommentController extends Controller
{
/**
* @Route("/edit/{id}", name = "post_edit")
*/
public function editAction(Post $post)
{
}
}
use SensioBundleFrameworkExtraBundleConfigurationRoute;
!
!
class CommentController extends Controller
{
/**
* @Route("/edit/{id}", name = "post_edit")
*/
public function editAction($id)
{
$em = $this->getDoctrine()->getManager();
$post = $em->getRepository('AppBundle:Post')->find($id);
!
if (!$post) {
throw $this->createNotFoundException();
}
}
}
Un controlador Symfony de ejemplo
namespace AppBundleController;
!
use AppBundleEntityPost;
use SymfonyBundleFrameworkBundleControllerController;
use SensioBundleFrameworkExtraBundleConfigurationRoute;
!
class BlogController extends Controller
{
/**
* @Route("/edit/{id}", name="post_edit")
*/
public function editAction(Post $post)
{
return $this->render('blog/edit.html.twig', array(
'post' => $post
));
}
}
Nuestro consejo
DESACOPLA ACOPLA
la
lógica de negocio
los
controladores
Los atajos de los controladores
$this->forward();
$this->redirect();
$this->redirectToRoute();
$this->getUser();
$this->getDoctrine();
$this->generateUrl();
$this->createNotFoundException();
$this->createAccessDeniedException()
Organizando el
proyecto
Seguridad
Anotaciones
Simplificaciones
Utiliza bcrypt
para codificar
las contraseñas
Combina varios
sistemas de
autorización
Restricciones poco granulares
# app/config/security.yml
security:
encoders:
# ...
!
providers:
# ...
!
firewalls:
# ...
!
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
Restricciones sencillas y comunes
use SensioBundleFrameworkExtraBundleConfigurationRoute;
use SensioBundleFrameworkExtraBundleConfigurationSecurity;
!
/**
* @Route("/new", name="admin_post_new")
* @Security("has_role('ROLE_ADMIN')")
*/
public function newAction()
{
// ...
}
Restricciones sencillas y comunes
use SensioBundleFrameworkExtraBundleConfigurationRoute;
use SensioBundleFrameworkExtraBundleConfigurationSecurity;
!
/**
* @Route("/new", name="admin_post_new")
*/
public function newAction()
{
if (false === $this->get('security.context')->isGranted('ROLE_ADMIN')) {
throw $this->createAccessDeniedException();
}
!
!
// ...
}
Restricciones sencillas y comunes
use AppBundleEntityPost;
use SensioBundleFrameworkExtraBundleConfigurationRoute;
use SensioBundleFrameworkExtraBundleConfigurationSecurity;
!
/**
* @Route("/{id}/edit", name="admin_post_edit")
* @Security("user.getEmail() == post.getAuthorEmail()")
*/
public function editAction(Post $post)
{
// ...
}
Restricciones sencillas y comunes
// src/AppBundle/Entity/Post.php
// ...
!
class Post
{
// ...
!
public function isAuthor(User $user = null)
{
return $user && $user->getEmail() == $this->getAuthorEmail();
}
}
Restricciones sencillas y comunes
use AppBundleEntityPost;
use SensioBundleFrameworkExtraBundleConfigurationSecurity;
!
/**
* @Route("/{id}/edit", name="admin_post_edit")
* @Security("post.isAuthor(user)")
*/
public function editAction(Post $post)
{
// ...
}
!
!
{% if post.isAuthor(app.user) %}
<a href=""> ... </a>
{% endif %}
Restricciones avanzadas (voters)
namespace AppBundleSecurity;
!
use SymfonyComponentSecurityCoreAuthorizationVoterAbstractVoter;
use SymfonyComponentSecurityCoreUserUserInterface;
!
class PostVoter extends AbstractVoter
{
protected function getSupportedAttributes()
{
return array('create', 'edit');
}
!
protected function getSupportedClasses()
{
return array('AppBundleEntityPost');
}
!
protected function isGranted($attribute, $post, $user = null)
{
// ...
}
}
Organizando el
proyecto
Seguridad
Anotaciones
Simplificaciones
Nombres de servicios en apps Symfony
// Servicios Symfony
$this->get('doctrine')
$this->get('logger')
$this->get('session')
$this->get('validator')
!
// Servicios de terceros
$this->get('imagine.filter.loader.thumbnail')
$this->get('knp_menu.renderer_provider')
$this->get('sonata.admin.form.filter.type.datetime_range')
Nombres de servicios propios
$this->get('slugger')
$this->get('parser')
$this->get('markdown_parser')
$this->get('stats_aggregator')
!
// Aceptable también
$this->get('app.slugger')
$this->get('app.parser')
$this->get('app.markdown_parser')
$this->get('app.stats_aggregator')
No definas parámetros para las clases
# app/config/services.yml
parameters:
slugger.class: AppBundleUtilsSlugger
!
services:
slugger:
class: "%slugger.class%"
No definas parámetros para las clases
# app/config/services.yml
parameters:
slugger.class: AppBundleUtilsSlugger
!
services:
slugger:
class: "%slugger.class%"
Innecesario y
poco útil en la
práctica
No definas parámetros que no cambian
# app/config/config.yml
parameters:
homepage.num_items: 10
!
// src/AppBundle/Entity/Post.php
class Post {
const NUM_ITEMS = 10;
!
// ...
}
No definas parámetros que no cambian
# app/config/config.yml
parameters:
homepage.num_items: 10
!
// src/AppBundle/Entity/Post.php
class Post {
const NUM_ITEMS = 10;
!
// ...
}
Este valor
seguramente no
cambia nunca
No añadas botones en los formularios
class PostType extends AbstractType {
public function buildForm($builder, $options) {
$builder
// ...
->add('save', 'submit', array('label' => 'Create Post'))
;
}
!
// ...
}
No añadas botones en los formularios
class PostType extends AbstractType {
public function buildForm($builder, $options) {
$builder
// ...
->add('save', 'submit', array('label' => 'Create Post'))
;
}
!
// ...
}
Te dificulta
reutilizar los
formularios
No utilices form_start y form_end
<form method="post" {{ form_enctype(form) }}>
{{ form_widget(form) }}
!
<input type="submit" value="Create"
class="btn btn-default pull-right" />
</form>
No generes las URLs en los tests
public function testBlogArchives()
{
$client = self::createClient();
$url = $client->getContainer()->get('router')->generate('blog_archives');
$client->request('GET', $url);
// ...
}
!
!
public function testBlogArchives()
{
$client = self::createClient();
$client->request('GET', '/blog/archives/');
// ...
}
No generes las URLs en los tests
public function testBlogArchives()
{
$client = self::createClient();
$url = $client->getContainer()->get('router')->generate('blog_archives');
$client->request('GET', $url);
// ...
}
!
!
public function testBlogArchives()
{
$client = self::createClient();
$client->request('GET', '/blog/archives/');
// ...
}
Si rompes la URL
no te enteras
Configuración
proyecto/app/config/
!" config.yml
!" parameters.yml
$" parameters.yml.dist
Configuración
no cambia de un ordenador a otro
proyecto/app/config/
!" config.yml
!" parameters.yml
$" parameters.yml.dist
Configuración
no cambia de un ordenador a otro
cambia de un ordenador a otro
no se sube al repositorio
proyecto/app/config/
!" config.yml
!" parameters.yml
$" parameters.yml.dist
Configuración
no cambia de un ordenador a otro
cambia de un ordenador a otro
no se sube al repositorio
este sí se sube al repositorio
proyecto/app/config/
!" config.yml
!" parameters.yml
$" parameters.yml.dist
No utilices una configuración semántica
public function getConfigTreeBuilder() {
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('framework');
!
$rootNode
->children()
->scalarNode('secret')->end()
->scalarNode('http_method_override')
->info("Set true to enable support for ...”)
->defaultTrue()
->end()
->arrayNode('trusted_proxies')
->beforeNormalization()
->ifTrue(function ($v) { return !is_array($v) && null !== $v; })
->then(function ($v) { return is_bool($v) ? array() : preg_split('/s*,s*/', $v); })
->end()
->prototype('scalar')
->validate()
->ifTrue(function ($v) {
if (empty($v)) {
return false;
}
!
if (false !== strpos($v, '/')) {
Sólo es útil en
configuraciones
muy complejas
Conclusiones
Conjunto de técnicas que
puedes utilizar para desarrollar
aplicaciones Symfony como
recomiendan sus creadores.
Todo es opcional y no es
necesario utilizar todas las
buenas prácticas a la vez.
Estas buenas prácticas no
sirven en algunos proyectos
y escenarios concretos.
Aunque no las sigas, te
pueden servir para crear tus
propias buenas prácticas.
Nadie conoce tu trabajo y tus
circunstancias como tu. Por eso
las mejores buenas prácticas
son tus buenas prácticas.
Muchas gracias.
¿Preguntas, comentarios?
SensioLabs

Mais conteúdo relacionado

Mais procurados

Mi primer programa en Symfony2
Mi primer programa en Symfony2Mi primer programa en Symfony2
Mi primer programa en Symfony2César Hernández
 
Symfony2: Interacción con CSS, JS y HTML5
Symfony2: Interacción con CSS, JS y HTML5Symfony2: Interacción con CSS, JS y HTML5
Symfony2: Interacción con CSS, JS y HTML5Raul Fraile
 
deSymfony 2013 - Creando aplicaciones web desde otro ángulo con Symfony y A...
deSymfony 2013 -  Creando aplicaciones web desde otro ángulo con Symfony y A...deSymfony 2013 -  Creando aplicaciones web desde otro ángulo con Symfony y A...
deSymfony 2013 - Creando aplicaciones web desde otro ángulo con Symfony y A...Pablo Godel
 
Introducción a PHP - Programador PHP - UGR
Introducción a PHP - Programador PHP - UGRIntroducción a PHP - Programador PHP - UGR
Introducción a PHP - Programador PHP - UGRJuan Belón Pérez
 
Curso Avanzado PHP para EHU/UPV
Curso Avanzado PHP para EHU/UPVCurso Avanzado PHP para EHU/UPV
Curso Avanzado PHP para EHU/UPVIrontec
 
Programacion - Php
Programacion - PhpProgramacion - Php
Programacion - PhpPROD LARD
 
PHP Avanzado: Patrones de diseño
PHP Avanzado: Patrones de diseñoPHP Avanzado: Patrones de diseño
PHP Avanzado: Patrones de diseñoRightster
 
Desymfony 2011 - Tutorial #1: Instalacion y primeros pasos
Desymfony 2011 - Tutorial #1: Instalacion y primeros pasosDesymfony 2011 - Tutorial #1: Instalacion y primeros pasos
Desymfony 2011 - Tutorial #1: Instalacion y primeros pasosJavier Eguiluz
 
PHP Avanzado: Seguridad Web
PHP Avanzado: Seguridad WebPHP Avanzado: Seguridad Web
PHP Avanzado: Seguridad WebRightster
 
Desymfony 2011 - Introducción a Symfony2
Desymfony 2011 - Introducción a Symfony2Desymfony 2011 - Introducción a Symfony2
Desymfony 2011 - Introducción a Symfony2Javier Eguiluz
 
Chamilo para-desarrolladores-1.9
Chamilo para-desarrolladores-1.9Chamilo para-desarrolladores-1.9
Chamilo para-desarrolladores-1.9Chamilo Association
 
Desarrollando aplicaciones web con Zope 3
Desarrollando aplicaciones web con Zope 3Desarrollando aplicaciones web con Zope 3
Desarrollando aplicaciones web con Zope 3Roberto Allende
 

Mais procurados (20)

Mi primer programa en Symfony2
Mi primer programa en Symfony2Mi primer programa en Symfony2
Mi primer programa en Symfony2
 
Composer: Gestionando dependencias en PHP
Composer: Gestionando dependencias en PHP Composer: Gestionando dependencias en PHP
Composer: Gestionando dependencias en PHP
 
Curso Php
Curso PhpCurso Php
Curso Php
 
Symfony2: Interacción con CSS, JS y HTML5
Symfony2: Interacción con CSS, JS y HTML5Symfony2: Interacción con CSS, JS y HTML5
Symfony2: Interacción con CSS, JS y HTML5
 
deSymfony 2013 - Creando aplicaciones web desde otro ángulo con Symfony y A...
deSymfony 2013 -  Creando aplicaciones web desde otro ángulo con Symfony y A...deSymfony 2013 -  Creando aplicaciones web desde otro ángulo con Symfony y A...
deSymfony 2013 - Creando aplicaciones web desde otro ángulo con Symfony y A...
 
Introducción a PHP - Programador PHP - UGR
Introducción a PHP - Programador PHP - UGRIntroducción a PHP - Programador PHP - UGR
Introducción a PHP - Programador PHP - UGR
 
Curso Avanzado PHP para EHU/UPV
Curso Avanzado PHP para EHU/UPVCurso Avanzado PHP para EHU/UPV
Curso Avanzado PHP para EHU/UPV
 
9.laravel
9.laravel9.laravel
9.laravel
 
Intro a cakephp
Intro a cakephpIntro a cakephp
Intro a cakephp
 
Conociendo PHP
Conociendo PHPConociendo PHP
Conociendo PHP
 
Programacion - Php
Programacion - PhpProgramacion - Php
Programacion - Php
 
PHP Avanzado: Patrones de diseño
PHP Avanzado: Patrones de diseñoPHP Avanzado: Patrones de diseño
PHP Avanzado: Patrones de diseño
 
Desymfony 2011 - Tutorial #1: Instalacion y primeros pasos
Desymfony 2011 - Tutorial #1: Instalacion y primeros pasosDesymfony 2011 - Tutorial #1: Instalacion y primeros pasos
Desymfony 2011 - Tutorial #1: Instalacion y primeros pasos
 
PHP Avanzado: Seguridad Web
PHP Avanzado: Seguridad WebPHP Avanzado: Seguridad Web
PHP Avanzado: Seguridad Web
 
Desymfony 2011 - Introducción a Symfony2
Desymfony 2011 - Introducción a Symfony2Desymfony 2011 - Introducción a Symfony2
Desymfony 2011 - Introducción a Symfony2
 
Manual de PHP Basico
Manual de PHP BasicoManual de PHP Basico
Manual de PHP Basico
 
4.Programación con PHP y MySQL
4.Programación con PHP y MySQL4.Programación con PHP y MySQL
4.Programación con PHP y MySQL
 
Chamilo para-desarrolladores-1.9
Chamilo para-desarrolladores-1.9Chamilo para-desarrolladores-1.9
Chamilo para-desarrolladores-1.9
 
Iniciacion a PHP (I)
Iniciacion a PHP (I)Iniciacion a PHP (I)
Iniciacion a PHP (I)
 
Desarrollando aplicaciones web con Zope 3
Desarrollando aplicaciones web con Zope 3Desarrollando aplicaciones web con Zope 3
Desarrollando aplicaciones web con Zope 3
 

Destaque

Marcos quesada caching_sf2
Marcos quesada caching_sf2Marcos quesada caching_sf2
Marcos quesada caching_sf2symfony_bcn
 
Desarrollo rápido con PHP y Symfony (I): Introducción a Symfony
Desarrollo rápido con PHP y Symfony (I): Introducción a SymfonyDesarrollo rápido con PHP y Symfony (I): Introducción a Symfony
Desarrollo rápido con PHP y Symfony (I): Introducción a SymfonyDavid J. Brenes
 
0.Indice de Contenidos
0.Indice de Contenidos0.Indice de Contenidos
0.Indice de Contenidoslarasaregune
 
1.Introduccion (diseño con CSS)
1.Introduccion (diseño con CSS)1.Introduccion (diseño con CSS)
1.Introduccion (diseño con CSS)larasaregune
 
3.Propiedades (diseño con CSS)
3.Propiedades (diseño con CSS)3.Propiedades (diseño con CSS)
3.Propiedades (diseño con CSS)larasaregune
 
2.Sintaxis (diseño con CSS)
2.Sintaxis (diseño con CSS)2.Sintaxis (diseño con CSS)
2.Sintaxis (diseño con CSS)larasaregune
 
0.Indice de Contenidos (diseño web con CSS)
0.Indice de Contenidos (diseño web con CSS)0.Indice de Contenidos (diseño web con CSS)
0.Indice de Contenidos (diseño web con CSS)larasaregune
 
0.Indice De Contenidos
0.Indice De Contenidos0.Indice De Contenidos
0.Indice De Contenidoslarasaregune
 
Buenas Prácticas de CSS
Buenas Prácticas de CSSBuenas Prácticas de CSS
Buenas Prácticas de CSSJavier España
 
1.Introduccion (diseño web con CSS)
1.Introduccion (diseño web con CSS)1.Introduccion (diseño web con CSS)
1.Introduccion (diseño web con CSS)larasaregune
 
3.Propiedades (diseño con CSS)
3.Propiedades (diseño con CSS)3.Propiedades (diseño con CSS)
3.Propiedades (diseño con CSS)larasaregune
 
El posicionamiento explicado en 9 pasos
El posicionamiento explicado en 9 pasosEl posicionamiento explicado en 9 pasos
El posicionamiento explicado en 9 pasosYadith Gomez Nolasco
 
4.Estructura (diseño con CSS)
4.Estructura (diseño con CSS)4.Estructura (diseño con CSS)
4.Estructura (diseño con CSS)larasaregune
 
CSS - Arquitectura Escalable y Modular
CSS - Arquitectura Escalable y ModularCSS - Arquitectura Escalable y Modular
CSS - Arquitectura Escalable y Modularrodboc
 
Web Performance Optimization: Mejorando el proceso de carga
Web Performance Optimization: Mejorando el proceso de cargaWeb Performance Optimization: Mejorando el proceso de carga
Web Performance Optimization: Mejorando el proceso de cargaJesus Pernas Alonso
 
Formularios html
Formularios htmlFormularios html
Formularios htmlArtmio
 
Haml y Sass: HTML y CSS dietéticos
Haml y Sass: HTML y CSS dietéticosHaml y Sass: HTML y CSS dietéticos
Haml y Sass: HTML y CSS dietéticosDAVID GRILLI
 

Destaque (20)

Marcos quesada caching_sf2
Marcos quesada caching_sf2Marcos quesada caching_sf2
Marcos quesada caching_sf2
 
Symfony Components
Symfony ComponentsSymfony Components
Symfony Components
 
Desarrollo rápido con PHP y Symfony (I): Introducción a Symfony
Desarrollo rápido con PHP y Symfony (I): Introducción a SymfonyDesarrollo rápido con PHP y Symfony (I): Introducción a Symfony
Desarrollo rápido con PHP y Symfony (I): Introducción a Symfony
 
Symfony. La guia definitiva
Symfony. La guia definitivaSymfony. La guia definitiva
Symfony. La guia definitiva
 
0.Indice de Contenidos
0.Indice de Contenidos0.Indice de Contenidos
0.Indice de Contenidos
 
1.Introduccion (diseño con CSS)
1.Introduccion (diseño con CSS)1.Introduccion (diseño con CSS)
1.Introduccion (diseño con CSS)
 
3.Propiedades (diseño con CSS)
3.Propiedades (diseño con CSS)3.Propiedades (diseño con CSS)
3.Propiedades (diseño con CSS)
 
2.Sintaxis (diseño con CSS)
2.Sintaxis (diseño con CSS)2.Sintaxis (diseño con CSS)
2.Sintaxis (diseño con CSS)
 
0.Indice de Contenidos (diseño web con CSS)
0.Indice de Contenidos (diseño web con CSS)0.Indice de Contenidos (diseño web con CSS)
0.Indice de Contenidos (diseño web con CSS)
 
0.Indice De Contenidos
0.Indice De Contenidos0.Indice De Contenidos
0.Indice De Contenidos
 
Paso apaso de html
Paso apaso de htmlPaso apaso de html
Paso apaso de html
 
Buenas Prácticas de CSS
Buenas Prácticas de CSSBuenas Prácticas de CSS
Buenas Prácticas de CSS
 
1.Introduccion (diseño web con CSS)
1.Introduccion (diseño web con CSS)1.Introduccion (diseño web con CSS)
1.Introduccion (diseño web con CSS)
 
3.Propiedades (diseño con CSS)
3.Propiedades (diseño con CSS)3.Propiedades (diseño con CSS)
3.Propiedades (diseño con CSS)
 
El posicionamiento explicado en 9 pasos
El posicionamiento explicado en 9 pasosEl posicionamiento explicado en 9 pasos
El posicionamiento explicado en 9 pasos
 
4.Estructura (diseño con CSS)
4.Estructura (diseño con CSS)4.Estructura (diseño con CSS)
4.Estructura (diseño con CSS)
 
CSS - Arquitectura Escalable y Modular
CSS - Arquitectura Escalable y ModularCSS - Arquitectura Escalable y Modular
CSS - Arquitectura Escalable y Modular
 
Web Performance Optimization: Mejorando el proceso de carga
Web Performance Optimization: Mejorando el proceso de cargaWeb Performance Optimization: Mejorando el proceso de carga
Web Performance Optimization: Mejorando el proceso de carga
 
Formularios html
Formularios htmlFormularios html
Formularios html
 
Haml y Sass: HTML y CSS dietéticos
Haml y Sass: HTML y CSS dietéticosHaml y Sass: HTML y CSS dietéticos
Haml y Sass: HTML y CSS dietéticos
 

Semelhante a Las buenas prácticas oficiales para aplicaciones Symfony

Herramientas para desarrollar rápidamente
Herramientas para desarrollar rápidamenteHerramientas para desarrollar rápidamente
Herramientas para desarrollar rápidamenteCarlos Toxtli
 
BDD - Configuración de un proyecto móvil (iOS - Android)
BDD - Configuración de un proyecto móvil (iOS - Android)BDD - Configuración de un proyecto móvil (iOS - Android)
BDD - Configuración de un proyecto móvil (iOS - Android)Sofia Swidarowicz
 
7 Gemas de Ruby on Rails que podrían salvarte el dia
7 Gemas de Ruby on Rails que podrían salvarte el dia7 Gemas de Ruby on Rails que podrían salvarte el dia
7 Gemas de Ruby on Rails que podrían salvarte el diaFrancisco Aranda
 
Desarrollo de aplicaciones multiplataforma 2/2
Desarrollo de aplicaciones multiplataforma 2/2Desarrollo de aplicaciones multiplataforma 2/2
Desarrollo de aplicaciones multiplataforma 2/2Ignacio Muñoz Vicente
 
Ionic: el framework para crear aplicaciones-hibridas-multiplataforma
Ionic: el framework para crear aplicaciones-hibridas-multiplataformaIonic: el framework para crear aplicaciones-hibridas-multiplataforma
Ionic: el framework para crear aplicaciones-hibridas-multiplataformaQuasarMaximus
 
Desarrollo de Mobile Web Apps
Desarrollo de Mobile Web AppsDesarrollo de Mobile Web Apps
Desarrollo de Mobile Web AppsAsier Marqués
 
Presentación de zan php
Presentación de zan phpPresentación de zan php
Presentación de zan phpCarlos Zantana
 
IONIC, el framework para crear aplicaciones híbridas multiplataforma
IONIC, el framework para crear aplicaciones híbridas multiplataformaIONIC, el framework para crear aplicaciones híbridas multiplataforma
IONIC, el framework para crear aplicaciones híbridas multiplataformabetabeers
 
Emprendiendo con Wordpress
Emprendiendo con WordpressEmprendiendo con Wordpress
Emprendiendo con WordpressYtzvan Mastino
 
Diseñando la web móvil con HTML5 y CSS3
Diseñando la web móvil con HTML5 y CSS3Diseñando la web móvil con HTML5 y CSS3
Diseñando la web móvil con HTML5 y CSS3Marta Armada
 
Como hacer una pagina web
Como hacer una pagina webComo hacer una pagina web
Como hacer una pagina webAyllen Sanchez
 
Desarrollo Móvil Multiplataforma
Desarrollo Móvil MultiplataformaDesarrollo Móvil Multiplataforma
Desarrollo Móvil MultiplataformaAbraham Barrera
 
Abraham Barrera - dev-cross-mobile
Abraham Barrera - dev-cross-mobileAbraham Barrera - dev-cross-mobile
Abraham Barrera - dev-cross-mobileStarTech Conference
 
Hackaton Globant - Windows Phone (snnipets and tips)
Hackaton Globant - Windows Phone (snnipets and tips)Hackaton Globant - Windows Phone (snnipets and tips)
Hackaton Globant - Windows Phone (snnipets and tips)Sorey García
 
Desarrollo de aplicaciones multiplataforma 1/2
Desarrollo de aplicaciones multiplataforma 1/2Desarrollo de aplicaciones multiplataforma 1/2
Desarrollo de aplicaciones multiplataforma 1/2Ignacio Muñoz Vicente
 
Python en la Web Semántica
Python en la Web SemánticaPython en la Web Semántica
Python en la Web SemánticaSantiago Coffey
 

Semelhante a Las buenas prácticas oficiales para aplicaciones Symfony (20)

2014 04 padrino
2014 04 padrino2014 04 padrino
2014 04 padrino
 
Herramientas para desarrollar rápidamente
Herramientas para desarrollar rápidamenteHerramientas para desarrollar rápidamente
Herramientas para desarrollar rápidamente
 
BDD - Configuración de un proyecto móvil (iOS - Android)
BDD - Configuración de un proyecto móvil (iOS - Android)BDD - Configuración de un proyecto móvil (iOS - Android)
BDD - Configuración de un proyecto móvil (iOS - Android)
 
7 Gemas de Ruby on Rails que podrían salvarte el dia
7 Gemas de Ruby on Rails que podrían salvarte el dia7 Gemas de Ruby on Rails que podrían salvarte el dia
7 Gemas de Ruby on Rails que podrían salvarte el dia
 
Desarrollo de aplicaciones multiplataforma 2/2
Desarrollo de aplicaciones multiplataforma 2/2Desarrollo de aplicaciones multiplataforma 2/2
Desarrollo de aplicaciones multiplataforma 2/2
 
Ionic: el framework para crear aplicaciones-hibridas-multiplataforma
Ionic: el framework para crear aplicaciones-hibridas-multiplataformaIonic: el framework para crear aplicaciones-hibridas-multiplataforma
Ionic: el framework para crear aplicaciones-hibridas-multiplataforma
 
Desarrollo de Mobile Web Apps
Desarrollo de Mobile Web AppsDesarrollo de Mobile Web Apps
Desarrollo de Mobile Web Apps
 
Presentación de zan php
Presentación de zan phpPresentación de zan php
Presentación de zan php
 
IONIC, el framework para crear aplicaciones híbridas multiplataforma
IONIC, el framework para crear aplicaciones híbridas multiplataformaIONIC, el framework para crear aplicaciones híbridas multiplataforma
IONIC, el framework para crear aplicaciones híbridas multiplataforma
 
Emprendiendo con Wordpress
Emprendiendo con WordpressEmprendiendo con Wordpress
Emprendiendo con Wordpress
 
Diseñando la web móvil con HTML5 y CSS3
Diseñando la web móvil con HTML5 y CSS3Diseñando la web móvil con HTML5 y CSS3
Diseñando la web móvil con HTML5 y CSS3
 
Como hacer una pagina web
Como hacer una pagina webComo hacer una pagina web
Como hacer una pagina web
 
Introducción a Flask
Introducción a FlaskIntroducción a Flask
Introducción a Flask
 
Desarrollo Móvil Multiplataforma
Desarrollo Móvil MultiplataformaDesarrollo Móvil Multiplataforma
Desarrollo Móvil Multiplataforma
 
Abraham Barrera - dev-cross-mobile
Abraham Barrera - dev-cross-mobileAbraham Barrera - dev-cross-mobile
Abraham Barrera - dev-cross-mobile
 
Hackaton Globant - Windows Phone (snnipets and tips)
Hackaton Globant - Windows Phone (snnipets and tips)Hackaton Globant - Windows Phone (snnipets and tips)
Hackaton Globant - Windows Phone (snnipets and tips)
 
Desarrollo de aplicaciones multiplataforma 1/2
Desarrollo de aplicaciones multiplataforma 1/2Desarrollo de aplicaciones multiplataforma 1/2
Desarrollo de aplicaciones multiplataforma 1/2
 
Aplicaciones
AplicacionesAplicaciones
Aplicaciones
 
Mini curse
Mini curseMini curse
Mini curse
 
Python en la Web Semántica
Python en la Web SemánticaPython en la Web Semántica
Python en la Web Semántica
 

Último

International Women's Day Sucre 2024 (IWD)
International Women's Day Sucre 2024 (IWD)International Women's Day Sucre 2024 (IWD)
International Women's Day Sucre 2024 (IWD)GDGSucre
 
Proyecto integrador. Las TIC en la sociedad S4.pptx
Proyecto integrador. Las TIC en la sociedad S4.pptxProyecto integrador. Las TIC en la sociedad S4.pptx
Proyecto integrador. Las TIC en la sociedad S4.pptx241521559
 
9egb-lengua y Literatura.pdf_texto del estudiante
9egb-lengua y Literatura.pdf_texto del estudiante9egb-lengua y Literatura.pdf_texto del estudiante
9egb-lengua y Literatura.pdf_texto del estudianteAndreaHuertas24
 
pruebas unitarias unitarias en java con JUNIT
pruebas unitarias unitarias en java con JUNITpruebas unitarias unitarias en java con JUNIT
pruebas unitarias unitarias en java con JUNITMaricarmen Sánchez Ruiz
 
POWER POINT YUCRAElabore una PRESENTACIÓN CORTA sobre el video película: La C...
POWER POINT YUCRAElabore una PRESENTACIÓN CORTA sobre el video película: La C...POWER POINT YUCRAElabore una PRESENTACIÓN CORTA sobre el video película: La C...
POWER POINT YUCRAElabore una PRESENTACIÓN CORTA sobre el video película: La C...silviayucra2
 
Redes direccionamiento y subredes ipv4 2024 .pdf
Redes direccionamiento y subredes ipv4 2024 .pdfRedes direccionamiento y subredes ipv4 2024 .pdf
Redes direccionamiento y subredes ipv4 2024 .pdfsoporteupcology
 
guía de registro de slideshare por Brayan Joseph
guía de registro de slideshare por Brayan Josephguía de registro de slideshare por Brayan Joseph
guía de registro de slideshare por Brayan JosephBRAYANJOSEPHPEREZGOM
 
CLASE DE TECNOLOGIA E INFORMATICA PRIMARIA
CLASE  DE TECNOLOGIA E INFORMATICA PRIMARIACLASE  DE TECNOLOGIA E INFORMATICA PRIMARIA
CLASE DE TECNOLOGIA E INFORMATICA PRIMARIAWilbisVega
 
Global Azure Lima 2024 - Integración de Datos con Microsoft Fabric
Global Azure Lima 2024 - Integración de Datos con Microsoft FabricGlobal Azure Lima 2024 - Integración de Datos con Microsoft Fabric
Global Azure Lima 2024 - Integración de Datos con Microsoft FabricKeyla Dolores Méndez
 
EPA-pdf resultado da prova presencial Uninove
EPA-pdf resultado da prova presencial UninoveEPA-pdf resultado da prova presencial Uninove
EPA-pdf resultado da prova presencial UninoveFagnerLisboa3
 
Presentación guía sencilla en Microsoft Excel.pptx
Presentación guía sencilla en Microsoft Excel.pptxPresentación guía sencilla en Microsoft Excel.pptx
Presentación guía sencilla en Microsoft Excel.pptxLolaBunny11
 
Desarrollo Web Moderno con Svelte 2024.pdf
Desarrollo Web Moderno con Svelte 2024.pdfDesarrollo Web Moderno con Svelte 2024.pdf
Desarrollo Web Moderno con Svelte 2024.pdfJulian Lamprea
 
Trabajo Mas Completo De Excel en clase tecnología
Trabajo Mas Completo De Excel en clase tecnologíaTrabajo Mas Completo De Excel en clase tecnología
Trabajo Mas Completo De Excel en clase tecnologíassuserf18419
 

Último (13)

International Women's Day Sucre 2024 (IWD)
International Women's Day Sucre 2024 (IWD)International Women's Day Sucre 2024 (IWD)
International Women's Day Sucre 2024 (IWD)
 
Proyecto integrador. Las TIC en la sociedad S4.pptx
Proyecto integrador. Las TIC en la sociedad S4.pptxProyecto integrador. Las TIC en la sociedad S4.pptx
Proyecto integrador. Las TIC en la sociedad S4.pptx
 
9egb-lengua y Literatura.pdf_texto del estudiante
9egb-lengua y Literatura.pdf_texto del estudiante9egb-lengua y Literatura.pdf_texto del estudiante
9egb-lengua y Literatura.pdf_texto del estudiante
 
pruebas unitarias unitarias en java con JUNIT
pruebas unitarias unitarias en java con JUNITpruebas unitarias unitarias en java con JUNIT
pruebas unitarias unitarias en java con JUNIT
 
POWER POINT YUCRAElabore una PRESENTACIÓN CORTA sobre el video película: La C...
POWER POINT YUCRAElabore una PRESENTACIÓN CORTA sobre el video película: La C...POWER POINT YUCRAElabore una PRESENTACIÓN CORTA sobre el video película: La C...
POWER POINT YUCRAElabore una PRESENTACIÓN CORTA sobre el video película: La C...
 
Redes direccionamiento y subredes ipv4 2024 .pdf
Redes direccionamiento y subredes ipv4 2024 .pdfRedes direccionamiento y subredes ipv4 2024 .pdf
Redes direccionamiento y subredes ipv4 2024 .pdf
 
guía de registro de slideshare por Brayan Joseph
guía de registro de slideshare por Brayan Josephguía de registro de slideshare por Brayan Joseph
guía de registro de slideshare por Brayan Joseph
 
CLASE DE TECNOLOGIA E INFORMATICA PRIMARIA
CLASE  DE TECNOLOGIA E INFORMATICA PRIMARIACLASE  DE TECNOLOGIA E INFORMATICA PRIMARIA
CLASE DE TECNOLOGIA E INFORMATICA PRIMARIA
 
Global Azure Lima 2024 - Integración de Datos con Microsoft Fabric
Global Azure Lima 2024 - Integración de Datos con Microsoft FabricGlobal Azure Lima 2024 - Integración de Datos con Microsoft Fabric
Global Azure Lima 2024 - Integración de Datos con Microsoft Fabric
 
EPA-pdf resultado da prova presencial Uninove
EPA-pdf resultado da prova presencial UninoveEPA-pdf resultado da prova presencial Uninove
EPA-pdf resultado da prova presencial Uninove
 
Presentación guía sencilla en Microsoft Excel.pptx
Presentación guía sencilla en Microsoft Excel.pptxPresentación guía sencilla en Microsoft Excel.pptx
Presentación guía sencilla en Microsoft Excel.pptx
 
Desarrollo Web Moderno con Svelte 2024.pdf
Desarrollo Web Moderno con Svelte 2024.pdfDesarrollo Web Moderno con Svelte 2024.pdf
Desarrollo Web Moderno con Svelte 2024.pdf
 
Trabajo Mas Completo De Excel en clase tecnología
Trabajo Mas Completo De Excel en clase tecnologíaTrabajo Mas Completo De Excel en clase tecnología
Trabajo Mas Completo De Excel en clase tecnología
 

Las buenas prácticas oficiales para aplicaciones Symfony

  • 7. Las buenas prácticas oficiales Conjunto de técnicas que puedes utilizar para desarrollar aplicaciones Symfony como recomiendan sus creadores.
  • 8. symfony.com/best-practices LIBROSWEB FABIEN POTENCIER RYAN WEAVER JAVIER EGUILUZ BUENAS PRÁCTICAS PARA APLICACIONES SYMFONY bit.ly/buenas-practicas-symfony 50 páginas 57 páginas
  • 9. ¿Por qué? Las buenas prácticas oficiosas complican mucho el desarrollo de aplicaciones y no siguen la filosofía pragmática de los creadores de Symfony.
  • 10. Definición de “Best Practice” A well defined procedure that is known to produce near-optimum results.
  • 11. Definición de “Pragmatic” Concerned with making decisions and actions that are useful in practice, not just theory.
  • 13. Las buenas prácticas Symfony • Reflejan las ideas de su creador.
  • 14. Las buenas prácticas Symfony • Reflejan las ideas de su creador. • Son opcionales.
  • 15. Las buenas prácticas Symfony • Reflejan las ideas de su creador. • Son opcionales. • Symfony no cambiará para obligarte a usarlas.
  • 16. Usa las buenas prácticas …
  • 17. Usa las buenas prácticas … • En proyectos pequeños y medianos.
  • 18. Usa las buenas prácticas … • En proyectos pequeños y medianos. • En proyectos web estándar.
  • 19. Usa las buenas prácticas … • En proyectos pequeños y medianos. • En proyectos web estándar. • Si eres nuevo/a en Symfony.
  • 20. No uses las buenas prácticas …
  • 21. No uses las buenas prácticas … • En bundles compartidos (públicos o privados).
  • 22. No uses las buenas prácticas … • En bundles compartidos (públicos o privados). • En aplicaciones muy complejas o con arquitecturas muy especiales.
  • 23. No uses las buenas prácticas … • En bundles compartidos (públicos o privados). • En aplicaciones muy complejas o con arquitecturas muy especiales. • Si tienes tus propias buenas prácticas.
  • 25. Estructura de una aplicación web proyecto/ !" app/ # !" config/ # $" Resources/ # $" views/ !" src/ !" vendor/ $" web/ !" css/ $" js/
  • 26. Estructura de una aplicación web configuración proyecto/ !" app/ # !" config/ # $" Resources/ # $" views/ !" src/ !" vendor/ $" web/ !" css/ $" js/
  • 27. Estructura de una aplicación web configuración plantillas proyecto/ !" app/ # !" config/ # $" Resources/ # $" views/ !" src/ !" vendor/ $" web/ !" css/ $" js/
  • 28. Estructura de una aplicación web configuración plantillas tu código proyecto/ !" app/ # !" config/ # $" Resources/ # $" views/ !" src/ !" vendor/ $" web/ !" css/ $" js/
  • 29. Estructura de una aplicación web configuración plantillas tu código dependencias proyecto/ !" app/ # !" config/ # $" Resources/ # $" views/ !" src/ !" vendor/ $" web/ !" css/ $" js/
  • 30. Estructura de una aplicación web configuración plantillas tu código dependencias assets proyecto/ !" app/ # !" config/ # $" Resources/ # $" views/ !" src/ !" vendor/ $" web/ !" css/ $" js/
  • 31. ¿Cómo crear un sistema de plugins?
  • 32. ¿Cómo crear un sistema de plugins? • Deben funcionar de manera autónoma.
  • 33. ¿Cómo crear un sistema de plugins? • Deben funcionar de manera autónoma. • Pueden definir su propia configuración.
  • 34. ¿Cómo crear un sistema de plugins? • Deben funcionar de manera autónoma. • Pueden definir su propia configuración. • Pueden incluir plantillas y assets.
  • 35. Estructura de un plugin plugin/ !" DependencyInjection/ # $" Configuration.php !" Resources/ # !" config/ # !" public/ # # !" css/ # # $" js/ # $" views/ $" ...
  • 36. Estructura de un plugin configuración plugin/ !" DependencyInjection/ # $" Configuration.php !" Resources/ # !" config/ # !" public/ # # !" css/ # # $" js/ # $" views/ $" ...
  • 37. Estructura de un plugin configuración assets plugin/ !" DependencyInjection/ # $" Configuration.php !" Resources/ # !" config/ # !" public/ # # !" css/ # # $" js/ # $" views/ $" ...
  • 38. Estructura de un plugin configuración plantillas assets plugin/ !" DependencyInjection/ # $" Configuration.php !" Resources/ # !" config/ # !" public/ # # !" css/ # # $" js/ # $" views/ $" ...
  • 39. Estructura de un plugin configuración plantillas tu código assets plugin/ !" DependencyInjection/ # $" Configuration.php !" Resources/ # !" config/ # !" public/ # # !" css/ # # $" js/ # $" views/ $" ...
  • 40. proyecto/ !" app/ # !" config/ # $" Resources/ # $" views/ !" src/ !" vendor/ $" web/ !" css/ $" js/ Aplicaciones vs plugins/bundles bundle/ !" DependencyInjection/ # $" Configuration.php !" Resources/ # !" config/ # !" public/ # # !" css/ # # $" js/ # $" views/ $" ...
  • 41. Los bundles son mini-aplicaciones Configuración Plantillas Código! fuente Assets Contenedor servicios Kernel Caché! y logs Aplicación ✔ ✔ ✔ ✔ ✔ ✔ ✔ Bundle ✔ ✔ ✔ ✔ ✔ ✘ ✘
  • 42. proyecto/ !" app/ # !" config/ # $" Resources/ # $" views/ !" src/ # # # # # # !" vendor/ $" web/ !" css/ $" js/ Los bundles en aplicaciones privadas AcmeUserBundle/ !" DependencyInjection/ # $" Configuration.php !" Resources/ # !" config/ # !" public/ # # !" css/ # # $" js/ # $" views/ $" ... AcmeProductBundle/ !" DependencyInjection/ # $" Configuration.php !" Resources/ # !" config/ # !" public/ # # !" css/ # # $" js/ # $" views/ $" ... AcmeOfferBundle/ !" DependencyInjection/ # $" Configuration.php !" Resources/ # !" config/ # !" public/ # # !" css/ # # $" js/ # $" views/ $" ... AcmeInvoiceBundle/ !" DependencyInjection/ # $" Configuration.php !" Resources/ # !" config/ # !" public/ # # !" css/ # # $" js/ # $" views/ $" ...
  • 43. proyecto/ !" app/ # !" config/ # $" Resources/ # $" views/ !" src/ # # # # # # !" vendor/ $" web/ !" css/ $" js/ Los bundles en aplicaciones privadas AcmeUserBundle/ !" DependencyInjection/ # $" Configuration.php !" Resources/ # !" config/ # !" public/ # # !" css/ # # $" js/ # $" views/ $" ... AcmeProductBundle/ !" DependencyInjection/ # $" Configuration.php !" Resources/ # !" config/ # !" public/ # # !" css/ # # $" js/ # $" views/ $" ... AcmeOfferBundle/ !" DependencyInjection/ # $" Configuration.php !" Resources/ # !" config/ # !" public/ # # !" css/ # # $" js/ # $" views/ $" ... AcmeInvoiceBundle/ !" DependencyInjection/ # $" Configuration.php !" Resources/ # !" config/ # !" public/ # # !" css/ # # $" js/ # $" views/ $" ...
  • 44. proyecto/ !" app/ # !" config/ # $" Resources/ # $" views/ !" src/ # # # # # # !" vendor/ $" web/ !" css/ $" js/ Los bundles en aplicaciones privadas AcmeUserBundle/ !" DependencyInjection/ # $" Configuration.php !" Resources/ # !" config/ # !" public/ # # !" css/ # # $" js/ # $" views/ $" ... AcmeProductBundle/ !" DependencyInjection/ # $" Configuration.php !" Resources/ # !" config/ # !" public/ # # !" css/ # # $" js/ # $" views/ $" ... AcmeOfferBundle/ !" DependencyInjection/ # $" Configuration.php !" Resources/ # !" config/ # !" public/ # # !" css/ # # $" js/ # $" views/ $" ... AcmeInvoiceBundle/ !" DependencyInjection/ # $" Configuration.php !" Resources/ # !" config/ # !" public/ # # !" css/ # # $" js/ # $" views/ $" ...
  • 45. Una verdad incómoda Es muy probable que los bundles de tus aplicaciones no sean bundles, sólo directorios que molestan.
  • 49. Crea un solo bundle llamado AppBundle
  • 50. aplicacion/ !" app/ !" src/ # !" ContactBundle/ # # $" Controller/ # # $" DefaultController.php # !" PaymentBundle/ # # $" Controller/ # # $" DefaultController.php # !" ProductBundle/ # # $" Controller/ # # $" DefaultController.php # $" UserBundle/ # $" Controller/ # $" DefaultController.php !" vendor/ $" web/ aplicacion/ !" app/ !" src/ # $" AppBundle/ # $" Controller/ # !" ContactController.php # !" PaymentController.php # !" ProductController.php # $" UserController.php !" vendor/ $" web/ Aplicaciones Symfony tradicionales Buenas Prácticas oficiales
  • 51. aplicacion/ !" app/ !" src/ # !" ContactBundle/ # # $" Controller/ # # $" DefaultController.php # !" PaymentBundle/ # # $" Controller/ # # $" DefaultController.php # !" ProductBundle/ # # $" Controller/ # # $" DefaultController.php # $" UserBundle/ # $" Controller/ # $" DefaultController.php !" vendor/ $" web/ aplicacion/ !" app/ !" src/ # $" AppBundle/ # $" Controller/ # !" ContactController.php # !" PaymentController.php # !" ProductController.php # $" UserController.php !" vendor/ $" web/ Aplicaciones Symfony tradicionales Buenas Prácticas oficiales 8directorios 4archivos
  • 52. aplicacion/ !" app/ !" src/ # !" ContactBundle/ # # $" Controller/ # # $" DefaultController.php # !" PaymentBundle/ # # $" Controller/ # # $" DefaultController.php # !" ProductBundle/ # # $" Controller/ # # $" DefaultController.php # $" UserBundle/ # $" Controller/ # $" DefaultController.php !" vendor/ $" web/ aplicacion/ !" app/ !" src/ # $" AppBundle/ # $" Controller/ # !" ContactController.php # !" PaymentController.php # !" ProductController.php # $" UserController.php !" vendor/ $" web/ Aplicaciones Symfony tradicionales Buenas Prácticas oficiales 8directorios 4archivos 2directorios 4archivos
  • 53. aplicacion/ !" app/ !" src/ # !" ContactBundle/ # # $" Controller/ # # $" DefaultController.php # !" PaymentBundle/ # # $" Controller/ # # $" DefaultController.php # !" ProductBundle/ # # $" Controller/ # # $" DefaultController.php # $" UserBundle/ # $" Controller/ # $" DefaultController.php !" vendor/ $" web/ aplicacion/ !" app/ !" src/ # $" AppBundle/ # $" Controller/ # !" ContactController.php # !" PaymentController.php # !" ProductController.php # $" UserController.php !" vendor/ $" web/ Aplicaciones Symfony tradicionales Buenas Prácticas oficiales
  • 54. aplicacion/ !" app/ !" src/ # !" ContactBundle/ # # $" Controller/ # # $" DefaultController.php # !" PaymentBundle/ # # $" Controller/ # # $" DefaultController.php # !" ProductBundle/ # # $" Controller/ # # $" DefaultController.php # $" UserBundle/ # $" Controller/ | !" GroupController.php | !" ProfileController.php | !" RegistrationController.php | !" ResettingController.php | $" SecurityController.php !" vendor/ $" web/ aplicacion/ !" app/ !" src/ # $" AppBundle/ # $" Controller/ # !" ContactController.php # !" PaymentController.php # !" ProductController.php # $" User/ | !" GroupController.php | !" ProfileController.php | !" RegistrationController.php | !" ResettingController.php | $" SecurityController.php !" vendor/ $" web/ Aplicaciones Symfony tradicionales Buenas Prácticas oficiales
  • 55. aplicacion/ !" app/ !" src/ # !" ContactBundle/ # # $" Controller/ # # $" DefaultController.php # !" PaymentBundle/ # # $" Controller/ # # $" DefaultController.php # !" ProductBundle/ # # $" Controller/ # # $" DefaultController.php # $" UserBundle/ # $" Controller/ | !" GroupController.php | !" ProfileController.php | !" RegistrationController.php | !" ResettingController.php | $" SecurityController.php !" vendor/ $" web/ aplicacion/ !" app/ !" src/ # $" AppBundle/ # $" Controller/ # !" ContactController.php # !" PaymentController.php # !" ProductController.php # $" User/ | !" GroupController.php | !" ProfileController.php | !" RegistrationController.php | !" ResettingController.php | $" SecurityController.php !" vendor/ $" web/ Aplicaciones Symfony tradicionales Buenas Prácticas oficiales 8directorios 8archivos
  • 56. aplicacion/ !" app/ !" src/ # !" ContactBundle/ # # $" Controller/ # # $" DefaultController.php # !" PaymentBundle/ # # $" Controller/ # # $" DefaultController.php # !" ProductBundle/ # # $" Controller/ # # $" DefaultController.php # $" UserBundle/ # $" Controller/ | !" GroupController.php | !" ProfileController.php | !" RegistrationController.php | !" ResettingController.php | $" SecurityController.php !" vendor/ $" web/ aplicacion/ !" app/ !" src/ # $" AppBundle/ # $" Controller/ # !" ContactController.php # !" PaymentController.php # !" ProductController.php # $" User/ | !" GroupController.php | !" ProfileController.php | !" RegistrationController.php | !" ResettingController.php | $" SecurityController.php !" vendor/ $" web/ Aplicaciones Symfony tradicionales Buenas Prácticas oficiales 8directorios 8archivos 3directorios 8archivos
  • 57. Configuración del enrutamiento # app/config/routing.yml app: resource: @AppBundle/Controller/ type: annotation
  • 58. No añadas un vendor en los bundles que no compartas
  • 59. No añadas un vendor a los bundles privados AcmeNetworksAcmeWebsiteMarketingBundle ! AcmeNetworksAcmeWebsiteMarketingBundle:Default:index.html.twig ! {{ render(controller( 'AcmeNetworksAcmeWebsiteMarketingBundle:Default:latestNews' )) }}
  • 60. No añadas un vendor a los bundles privados AcmeNetworksAcmeWebsiteMarketingBundle ! AcmeNetworksAcmeWebsiteMarketingBundle:Default:index.html.twig ! {{ render(controller( 'AcmeNetworksAcmeWebsiteMarketingBundle:Default:latestNews' )) }} Esto lo he visto con mis propios ojos
  • 62. Esta buena práctica es la que produce un mayor impacto positivo AVISO IMPORTANTE
  • 63. aplicacion/ !" app/ !" src/ # !" ContactBundle/ # # $" Resources/ # # $" views/ # # $" Default/ # # !" index.html.twig # # $" show.html.twig # . . . # $" ProductBundle/ # $" Resources/ # $" views/ # $" Default/ # !" index.html.twig # !" category.html.twig # $" show.html.twig !" vendor/ $" web/ your-application/ !" app/ # $" Resources/ # $" views/ # !" contact/ # # !" index.html.twig # # $" show.html.twig # . . . # $" product/ # !" index.html.twig # !" category.html.twig # $" show.html.twig !" vendor/ $" web/ Aplicaciones Symfony tradicionales Buenas Prácticas oficiales
  • 64. aplicacion/ !" app/ !" src/ # !" ContactBundle/ # # $" Resources/ # # $" views/ # # $" Default/ # # !" index.html.twig # # $" show.html.twig # . . . # $" ProductBundle/ # $" Resources/ # $" views/ # $" Default/ # !" index.html.twig # !" category.html.twig # $" show.html.twig !" vendor/ $" web/ your-application/ !" app/ # $" Resources/ # $" views/ # !" contact/ # # !" index.html.twig # # $" show.html.twig # . . . # $" product/ # !" index.html.twig # !" category.html.twig # $" show.html.twig !" vendor/ $" web/ Aplicaciones Symfony tradicionales Buenas Prácticas oficiales 8directorios 5archivos
  • 65. aplicacion/ !" app/ !" src/ # !" ContactBundle/ # # $" Resources/ # # $" views/ # # $" Default/ # # !" index.html.twig # # $" show.html.twig # . . . # $" ProductBundle/ # $" Resources/ # $" views/ # $" Default/ # !" index.html.twig # !" category.html.twig # $" show.html.twig !" vendor/ $" web/ your-application/ !" app/ # $" Resources/ # $" views/ # !" contact/ # # !" index.html.twig # # $" show.html.twig # . . . # $" product/ # !" index.html.twig # !" category.html.twig # $" show.html.twig !" vendor/ $" web/ Aplicaciones Symfony tradicionales Buenas Prácticas oficiales 8directorios 5archivos 4directorios 5archivos
  • 67. Centralizar las plantillas Cambia la vida a tus diseñadores/as
  • 68. Centralizar las plantillas Cambia la vida a tus diseñadores/as Simplifica mucho tu código
  • 69. Nueva organización de plantillas aplicacion/ $" app/Resources/views/ !" contact/ # !" index.html.twig # $" show.html.twig . . . ! $" product/ !" index.html.twig !" category.html.twig $" show.html.twig
  • 70. La nueva notación de las plantillas $this->render('AcmeDemoBunde:Default:index.html.twig'); $this->render('default/index.html.twig'); ! $this->render('AcmeDemoBundle::index.html.twig'); $this->render('index.html.twig');
  • 71. La nueva notación de las plantillas {% extends '::layout.html.twig' %} {% extends 'layout.html.twig' %} ! {{ include('AcmeDemoBundle:Default:subdir/index.html.twig') }} {{ include('default/subdir/index.html.twig') }} ! {{ include('AcmeDemoBundle:Default/subdir:index.html.twig') }} {{ include('default/subdir/index.html.twig') }}
  • 72. Los problemas de la notación tradicional AcmeDemoBundle:Default:subdir/index.html.twig
  • 73. Los problemas de la notación tradicional • Requiere explicársela a cada diseñador/programador. AcmeDemoBundle:Default:subdir/index.html.twig
  • 74. Los problemas de la notación tradicional • Requiere explicársela a cada diseñador/programador. • Tiene excepciones (alguna de sus partes puede estar vacía) e inconsistencias (subdirectorios). AcmeDemoBundle:Default:subdir/index.html.twig
  • 75. Los problemas de la notación tradicional • Requiere explicársela a cada diseñador/programador. • Tiene excepciones (alguna de sus partes puede estar vacía) e inconsistencias (subdirectorios). • No es inmediato saber dónde está la plantilla (debes traducir la notación a un directorio). AcmeDemoBundle:Default:subdir/index.html.twig
  • 77. Centralizar los assets (CSS, JavaScript) • Tiene las mismas ventajas que centralizar las plantillas.
  • 78. Organizando los assets web proyecto/ !" app/ !" src/ !" vendor/ $" web/ !" css/ # !" bootstrap.min.css # $" app.css $" js/ !" jquery.min.js $" app.js
  • 79. Organizando los assets web proyecto/ !" app/ !" src/ !" vendor/ $" web/ !" css/ # !" bootstrap.min.css # $" app.css $" js/ !" jquery.min.js $" app.js proyecto/ !" app/ # $" Resources/ # $" assets/ # !" scss/ # # !" bootstrap/ # # $" app.scss # $" js/ !" src/ !" vendor/ $" web/ !" css/app.css $" js/app.js
  • 80. En resumen • Si utilizas mal los bundles, estás repitiendo la estructura de la aplicación sin necesidad • Si no vas a compartir tus bundles, utiliza los directorios de la aplicación (app/ Resources/ y web/). • El número de archivos se mantiene, los directorios y la complejidad se reducen.
  • 83. Escala de sensibilidad para programadores Política Religión Fútbol Estándar de código Editor de código Anotaciones
  • 84. Anotaciones PHP use AppBundleEntityPost; use SensioBundleFrameworkExtraBundleConfigurationRoute; ! class CommentController extends Controller { /** * @Route("/edit/{id}", name = "post_edit") */ public function editAction(Post $post) { ... } ! /* * @Route("/edit/{id}", name = "post_edit") */ public function editAction(Post $post) { ... } }
  • 85. Anotaciones PHP use AppBundleEntityPost; use SensioBundleFrameworkExtraBundleConfigurationRoute; ! class CommentController extends Controller { /** * @Route("/edit/{id}", name = "post_edit") */ public function editAction(Post $post) { ... } ! /* * @Route("/edit/{id}", name = "post_edit") */ public function editAction(Post $post) { ... } } Anotación
  • 86. Anotaciones PHP use AppBundleEntityPost; use SensioBundleFrameworkExtraBundleConfigurationRoute; ! class CommentController extends Controller { /** * @Route("/edit/{id}", name = "post_edit") */ public function editAction(Post $post) { ... } ! /* * @Route("/edit/{id}", name = "post_edit") */ public function editAction(Post $post) { ... } } Anotación Comentario
  • 87. Anotaciones PHP /** @Route(...) */Anotación Comentario /* @Route(...) */
  • 89. Enrutamiento tradicional # app/config/routing.yml _admin_post: resource: '@AcmeAdminBundle/Resources/config/routing/post.yml' prefix: '/admin/post' ! # src/Acme/AdminBundle/Resources/config/routing/post.yml admin_post_show: pattern: '/{id}' defaults: { _controller: 'AcmeAdminBundle:Post:show' } ! ! namespace AcmeAdminBundleController; ! class PostController { public function showAction($id) { ... } }
  • 90. Enrutamiento con anotaciones namespace AppBundleControllerAdmin; ! use SymfonyBundleFrameworkBundleControllerController; use SensioBundleFrameworkExtraBundleConfigurationRoute; ! /** * @Route("/admin/post") */ class PostController extends Controller { /** * @Route("/{id}", name="admin_post_show") */ public function showAction($id) { ... } }
  • 92. La anotación @Template es mágica /** @Template() */ public function indexAction() { // ... return array('posts' => $posts); } ! ! public function indexAction() { // ... return $this->render('blog/index.html.twig', array( 'posts' => $posts )); }
  • 94. Los ParamConvertes en la práctica use SensioBundleFrameworkExtraBundleConfigurationRoute; use AppBundleEntityPost; ! class CommentController extends Controller { /** * @Route("/edit/{id}", name = "post_edit") */ public function editAction(Post $post) { } } use SensioBundleFrameworkExtraBundleConfigurationRoute; ! ! class CommentController extends Controller { /** * @Route("/edit/{id}", name = "post_edit") */ public function editAction($id) { $em = $this->getDoctrine()->getManager(); $post = $em->getRepository('AppBundle:Post')->find($id); ! if (!$post) { throw $this->createNotFoundException(); } } }
  • 95. Un controlador Symfony de ejemplo namespace AppBundleController; ! use AppBundleEntityPost; use SymfonyBundleFrameworkBundleControllerController; use SensioBundleFrameworkExtraBundleConfigurationRoute; ! class BlogController extends Controller { /** * @Route("/edit/{id}", name="post_edit") */ public function editAction(Post $post) { return $this->render('blog/edit.html.twig', array( 'post' => $post )); } }
  • 96. Nuestro consejo DESACOPLA ACOPLA la lógica de negocio los controladores
  • 97. Los atajos de los controladores $this->forward(); $this->redirect(); $this->redirectToRoute(); $this->getUser(); $this->getDoctrine(); $this->generateUrl(); $this->createNotFoundException(); $this->createAccessDeniedException()
  • 101. Restricciones poco granulares # app/config/security.yml security: encoders: # ... ! providers: # ... ! firewalls: # ... ! access_control: - { path: ^/admin, roles: ROLE_ADMIN }
  • 102. Restricciones sencillas y comunes use SensioBundleFrameworkExtraBundleConfigurationRoute; use SensioBundleFrameworkExtraBundleConfigurationSecurity; ! /** * @Route("/new", name="admin_post_new") * @Security("has_role('ROLE_ADMIN')") */ public function newAction() { // ... }
  • 103. Restricciones sencillas y comunes use SensioBundleFrameworkExtraBundleConfigurationRoute; use SensioBundleFrameworkExtraBundleConfigurationSecurity; ! /** * @Route("/new", name="admin_post_new") */ public function newAction() { if (false === $this->get('security.context')->isGranted('ROLE_ADMIN')) { throw $this->createAccessDeniedException(); } ! ! // ... }
  • 104. Restricciones sencillas y comunes use AppBundleEntityPost; use SensioBundleFrameworkExtraBundleConfigurationRoute; use SensioBundleFrameworkExtraBundleConfigurationSecurity; ! /** * @Route("/{id}/edit", name="admin_post_edit") * @Security("user.getEmail() == post.getAuthorEmail()") */ public function editAction(Post $post) { // ... }
  • 105. Restricciones sencillas y comunes // src/AppBundle/Entity/Post.php // ... ! class Post { // ... ! public function isAuthor(User $user = null) { return $user && $user->getEmail() == $this->getAuthorEmail(); } }
  • 106. Restricciones sencillas y comunes use AppBundleEntityPost; use SensioBundleFrameworkExtraBundleConfigurationSecurity; ! /** * @Route("/{id}/edit", name="admin_post_edit") * @Security("post.isAuthor(user)") */ public function editAction(Post $post) { // ... } ! ! {% if post.isAuthor(app.user) %} <a href=""> ... </a> {% endif %}
  • 107. Restricciones avanzadas (voters) namespace AppBundleSecurity; ! use SymfonyComponentSecurityCoreAuthorizationVoterAbstractVoter; use SymfonyComponentSecurityCoreUserUserInterface; ! class PostVoter extends AbstractVoter { protected function getSupportedAttributes() { return array('create', 'edit'); } ! protected function getSupportedClasses() { return array('AppBundleEntityPost'); } ! protected function isGranted($attribute, $post, $user = null) { // ... } }
  • 109. Nombres de servicios en apps Symfony // Servicios Symfony $this->get('doctrine') $this->get('logger') $this->get('session') $this->get('validator') ! // Servicios de terceros $this->get('imagine.filter.loader.thumbnail') $this->get('knp_menu.renderer_provider') $this->get('sonata.admin.form.filter.type.datetime_range')
  • 110. Nombres de servicios propios $this->get('slugger') $this->get('parser') $this->get('markdown_parser') $this->get('stats_aggregator') ! // Aceptable también $this->get('app.slugger') $this->get('app.parser') $this->get('app.markdown_parser') $this->get('app.stats_aggregator')
  • 111. No definas parámetros para las clases # app/config/services.yml parameters: slugger.class: AppBundleUtilsSlugger ! services: slugger: class: "%slugger.class%"
  • 112. No definas parámetros para las clases # app/config/services.yml parameters: slugger.class: AppBundleUtilsSlugger ! services: slugger: class: "%slugger.class%" Innecesario y poco útil en la práctica
  • 113. No definas parámetros que no cambian # app/config/config.yml parameters: homepage.num_items: 10 ! // src/AppBundle/Entity/Post.php class Post { const NUM_ITEMS = 10; ! // ... }
  • 114. No definas parámetros que no cambian # app/config/config.yml parameters: homepage.num_items: 10 ! // src/AppBundle/Entity/Post.php class Post { const NUM_ITEMS = 10; ! // ... } Este valor seguramente no cambia nunca
  • 115. No añadas botones en los formularios class PostType extends AbstractType { public function buildForm($builder, $options) { $builder // ... ->add('save', 'submit', array('label' => 'Create Post')) ; } ! // ... }
  • 116. No añadas botones en los formularios class PostType extends AbstractType { public function buildForm($builder, $options) { $builder // ... ->add('save', 'submit', array('label' => 'Create Post')) ; } ! // ... } Te dificulta reutilizar los formularios
  • 117. No utilices form_start y form_end <form method="post" {{ form_enctype(form) }}> {{ form_widget(form) }} ! <input type="submit" value="Create" class="btn btn-default pull-right" /> </form>
  • 118. No generes las URLs en los tests public function testBlogArchives() { $client = self::createClient(); $url = $client->getContainer()->get('router')->generate('blog_archives'); $client->request('GET', $url); // ... } ! ! public function testBlogArchives() { $client = self::createClient(); $client->request('GET', '/blog/archives/'); // ... }
  • 119. No generes las URLs en los tests public function testBlogArchives() { $client = self::createClient(); $url = $client->getContainer()->get('router')->generate('blog_archives'); $client->request('GET', $url); // ... } ! ! public function testBlogArchives() { $client = self::createClient(); $client->request('GET', '/blog/archives/'); // ... } Si rompes la URL no te enteras
  • 121. Configuración no cambia de un ordenador a otro proyecto/app/config/ !" config.yml !" parameters.yml $" parameters.yml.dist
  • 122. Configuración no cambia de un ordenador a otro cambia de un ordenador a otro no se sube al repositorio proyecto/app/config/ !" config.yml !" parameters.yml $" parameters.yml.dist
  • 123. Configuración no cambia de un ordenador a otro cambia de un ordenador a otro no se sube al repositorio este sí se sube al repositorio proyecto/app/config/ !" config.yml !" parameters.yml $" parameters.yml.dist
  • 124. No utilices una configuración semántica public function getConfigTreeBuilder() { $treeBuilder = new TreeBuilder(); $rootNode = $treeBuilder->root('framework'); ! $rootNode ->children() ->scalarNode('secret')->end() ->scalarNode('http_method_override') ->info("Set true to enable support for ...”) ->defaultTrue() ->end() ->arrayNode('trusted_proxies') ->beforeNormalization() ->ifTrue(function ($v) { return !is_array($v) && null !== $v; }) ->then(function ($v) { return is_bool($v) ? array() : preg_split('/s*,s*/', $v); }) ->end() ->prototype('scalar') ->validate() ->ifTrue(function ($v) { if (empty($v)) { return false; } ! if (false !== strpos($v, '/')) { Sólo es útil en configuraciones muy complejas
  • 126. Conjunto de técnicas que puedes utilizar para desarrollar aplicaciones Symfony como recomiendan sus creadores.
  • 127. Todo es opcional y no es necesario utilizar todas las buenas prácticas a la vez.
  • 128. Estas buenas prácticas no sirven en algunos proyectos y escenarios concretos.
  • 129. Aunque no las sigas, te pueden servir para crear tus propias buenas prácticas.
  • 130. Nadie conoce tu trabajo y tus circunstancias como tu. Por eso las mejores buenas prácticas son tus buenas prácticas.