SlideShare a Scribd company logo
C
THIRD PARTY BUNDLES DE SYMFONY
COMPLETAMENTE EXTENSIBLES
Y SOBREESCRIBIBLES.
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
gerfignaedytebfodavegmiguelvilata
araquemario almacbe frankey90 driera_comraulo79
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
wolfwolker JL_Laso
araquemario almacbe frankey90 driera_comraulo79
gerfignaedytebfodavegmiguelvilata
paolacaracola
BEST PRACTICES FOR REUSABLE
BUNDLES
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
BEST PRACTICE # 1
NOMBRE DE LOS BUNDLES
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
AcmeBlogBundle
AcmeBlogBundle
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
AcmeBundleBlogBundle
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
AcmeBlogBundle
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
PSR4
Vendor(Category)*BundleName ~ Bundle
CamelCase
Descriptivo y corto
No más de dos palabras
NOMBRE DE LOS BUNDLES:
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
BEST PRACTICE # 2
ESTRUCTURA DE DIRECTORIOS
¿Qué ficheros y carpetas son obligados?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
AcmeBlogBundle.php
README.(md | rst)
LICENSE
Resources/doc/index.rst
ESTRUCTURA DE LOS DIRECTORIOS:
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Commands → Command/
Controllers → Controller/
Service Container Extensions → DependencyInjection/
Model classes → Model/
Configuration → Resources/config/
Web Resources (CSS, JS, images) → Resources/public/
Translation files → Resources/translations/
Templates → Resources/views/
Unit and Functional Tests → Tests/
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
ESTRUCTURA DE LOS DIRECTORIOS:
¿Cómo se tiene que llamar la carpeta
donde estén los Listeners y/o
Subscribers?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
EventListener
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
El directorio de un bundle es de solo
lectura
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Y si tu bundle necesita generar algún
fichero, ¿dónde lo crearías?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Solo si formarán parte del repositorio...
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
app/logs o app/cache
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
CLASES
BEST PRACTICE # 3
ContentController.php del Bundle
AcmeBlogBundle
¿directorio?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Acme/BlogBundle/Controller/ContentController.php
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
ContentController.php del Bundle
AcmeBlogBundle
¿FQC?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
AcmeBlogBundleControllerContentController
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
SYMFONY CODING STANDARD
BEST PRACTICE # 4
class FooBar
{
const SOMECONST = 42;
/**
* @var string
*/
private $foo_bar;
private function transformText($dummy, array $options = array())
{
$defaultOptions = [
'some_default' => 'values',
'another_default' => 'more values'
];
foreach ($options as $option) {
if (!in_array($option, $defaultOptions)) {
throw new RuntimeException(sprintf('Unrecognized option "%s"', $option));
}
}
$mergedOptions = array_merge($defaultOptions,
$options
);
if (true === $dummy) {
return;
}
if ($dummy === 'string') {
if ('values' === $mergedOptions['some_default']) {
return substr($dummy, 0, 5);
}
return ucwords($dummy);
}
}
}
class FooBar
{
const SOMECONST = 42;
/**
* @var string
*/
private $foo_bar;
private function transformText($dummy, array $options = array())
{
$defaultOptions = [
'some_default' => 'values',
'another_default' => 'more values'
];
foreach ($options as $option) {
if (!in_array($option, $defaultOptions)) {
throw new RuntimeException(sprintf('Unrecognized option "%s"', $option));
}
}
$mergedOptions = array_merge($defaultOptions,
$options
);
if (true === $dummy) {
return;
}
if ($dummy === 'string') {
if ('values' === $mergedOptions['some_default']) {
return substr($dummy, 0, 5);
}
return ucwords($dummy);
}
}
}
Sufijo Listener si escucha a algún evento
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Clases Exception deben de ir en un
sub-space Exception
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
TESTS
BEST PRACTICE # 5
PHPUnit
Tests/
Los test funcionales solo deben testear la response y la
información de profiling si creas alguna.
No puede existir un test que sea AllTest.php
Tiene que haber un phpunit.xml.dist
TESTS
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
¿Cuánto % de cobertura tiene que
haber?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
>= 95%
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
DOCUMENTACIÓN
BEST PRACTICE # 6
PHPDoc.
reStructuredText en Resources/doc/
DOCUMENTACIÓN:
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
INSTRUCCIONES DE INSTALACIÓN
README.md
Step 1: Download the Bundle
---------------------------
composer require blabla/blabla
Step 2: Enable the Bundle
-------------------------
Step 3, Step 4, etc. otros requisitos como registrar rutas...
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
RUTAS
BEST PRACTICE # 7
¿Alias de AcmeBlogBundle?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
acme_blog
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Todas las rutas tiene que tener el alias
como prefijo
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
TRADUCCIONES
BEST PRACTICE # 8
¿formato recomendado yml, xliff, po ...?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
XLIFF
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
XLIFF
Symfony Best Practices
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
¿Nombre del dominio de las
traducciones para AcmeBlogBundle?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
acme_blog_domain
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Un bundle NO tiene que sobreescribir
otros dominios de traducción
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Un bundle NO tiene que sobreescribir
otros dominios de traducción
Symfony Best Practices
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
CONFIGURACIÓN
BEST PRACTICE # 9
Parámetros
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
# app/config/config.yml
parameters:
# @FrameworkBundle/Resources/config/translation.xml
translator.class: AcmeHelloBundleTranslationTranslator
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Semantic bundle configuration
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
# app/config/config.yml
acme_social:
twitter:
client_id: 123
client_secret: $ecret
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
// src/Acme/SocialBundle/DependencyInjection/Configuration.php
namespace AcmeSocialBundleDependencyInjection;
use SymfonyComponentConfigDefinitionBuilderTreeBuilder;
use SymfonyComponentConfigDefinitionConfigurationInterface;
class Configuration implements ConfigurationInterface
{
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('acme_social');
$rootNode
->children()
->arrayNode('twitter')
->children()
->integerNode('client_id')-> defaultValue(123123)->end()
->scalarNode('client_secret')-> defaultValue('k453jhdaj492')->end()
->end()
->end() // twitter
->end()
;
return $treeBuilder;
}
}
// src/Acme/SocialBundle/DependencyInjection/Configuration.php
namespace AcmeSocialBundleDependencyInjection;
use SymfonyComponentConfigDefinitionBuilderTreeBuilder;
use SymfonyComponentConfigDefinitionConfigurationInterface;
class Configuration implements ConfigurationInterface
{
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('acme_social');
$rootNode
->children()
->arrayNode('twitter')
->children()
->integerNode('client_id')-> defaultValue(123123)->end()
->scalarNode('client_secret')-> defaultValue('k453jhdaj492')->end()
->end()
->end() // twitter
->end()
;
return $treeBuilder;
}
}
VERSIONADO
BEST PRACTICE
#
10
Semantic Versioning Standard.
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
MAJOR.MINOR.PATCH
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
¿Qué implicaciones tiene estar en la
versión 0.x.x?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
“4 - Major version zero (0.y.z) is for initial
development. Anything may change at
any time. The public API should not be
considered stable.”
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
SERVICIOS
BEST PRACTICE # 11
¿Cómo tiene que ser el id de los
servicios?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
bundle_alias.service_id
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
¿Qué hacemos con los servicios que no
son usados por la aplicación si no
internamente en el bundle?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
services:
foo:
class: ExampleFoo
public: false
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
¿Qué implica que un servicio sea
privado?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
No se puede hacer: $container->get('foo');
Solo se puede inyectar en otro servicio en su definición.
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
¿Cómo vamos hasta aquí? ¿bien?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
MECANISMOS DE SOBRE-
ESCRITURA Y HERENCIA
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
BUNDLES
MECANISMOS... # 1
¿Cómo hacemos que un bundle herede
de otro?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Bundles
<?php
use SymfonyComponentHttpKernelBundleBundle;
class UserBundle extends Bundle
{
public function getParent()
{
return 'FOSUserBundle';
}
}
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
¿Qué implica esto?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Poder sobreescribir casi cualquier
archivo del bundle padre creándolo en
el mismo sitio que el padre.
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
CONTROLADORES
MECANISMOS... # 2
¿Cómo sobreescribimos el
comportamiento de un controlador?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Controladores
// src/UserBundle/Controller/RegistrationController.php
namespace UserBundleController;
use FOSUserBundleControllerRegistrationController as BaseController;
class RegistrationController extends BaseController
{
public function registerAction()
{
$response = parent::registerAction();
// ... do custom stuff
return $response;
}
}
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Controladores
// src/UserBundle/Controller/RegistrationController.php
namespace UserBundleController;
use FOSUserBundleControllerRegistrationController as BaseController;
class RegistrationController extends BaseController
{
public function registerAction()
{
$response = parent::registerAction();
// ... do custom stuff
return $response;
}
}
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
¿Siempre que una ruta apunte a ese
action de ese controlador se llamará al
sobreescrito?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
route_id:
path: /register
defaults: { _controller: FOSUserBundle:Registration:register }
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
¿De qué otra forma se puede hacer
referencia a un controlador?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
UserBundleControllerRegistrationController::registerAction
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
route_id:
path: /register
defaults: { _controller:
UserBundleControllerRegistrationController::registerAction }
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
¿y otra forma?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
¿se podría declarar como servicio un
controlador?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
services:
fos_user.registration_controller:
class: FOSUserBundleControllerRegistrationController
...
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
route_id:
path: /register
defaults: { _controller: fos_user.registration_controller:registerAction }
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
route_id:
path: /register
defaults: { _controller: fos_user.registration_controller:registerAction }
Sí, pero de otra forma. Más adelante!
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Por tanto, solo se sobreescribirá si se
usa ¿cómo?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
FOSUserBundle:Registration:register
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
FOSUserBundle:Registration:register
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
TEMPLATES
MECANISMOS... # 3
¿Cómo “encuentra” Symfony2 los
templates twig?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
::index.html.twig
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
AcmeBlogBundle::index.html.twig
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
AcmeBlogBundle:Blog:index.html.twig
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Orden de búsqueda
1. app/Resources/AcmeBlogBundle/views/layout.html.twig
2. src/Acme/BlogBundle/Resources/views/layout.html.twig
3. src/MyAcmeBlogBundle/Resources/views/layout.html.twig
- si fuera un bundle de vendors que hemos sobreescrito.
public function Bundle::getParent ( return ‘AcmeBlogBundle’; )
4. vendor/Acme/src/BlogBundle/Resources/views/layout.html.twig
- si fuera un bundle de vendors.
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
¿Qué dice Symfony Best Practices sobre
dónde tienen que ir los templates del
proyecto?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
app/Resources
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
¿por qué?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
RUTAS
MECANISMOS... # 4
“Routing is never automatically imported in
Symfony. If you want to include the routes from
any bundle, then they must be manually
imported from somewhere in your application
(e.g. app/config/routing.yml).”
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
“Routing is never automatically imported in
Symfony. If you want to include the routes from
any bundle, then they must be manually
imported from somewhere in your application
(e.g. app/config/routing.yml).”
Symfony Best Practices
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
“Copiar” las rutas del bundle y solo
importar y/o modificar las que se
deseen.
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
TRADUCCIONES
MECANISMOS... # 5
¿Qué son los dominios de las
traducciones?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
$translator->trans('Symfony is great');
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
¿Cuál es el dominio de esa traducción?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
messages.{lang}.{yml|po|xliff}
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
¿Cómo se selecciona el dominio en el
translator?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
$translator->trans('label.is_valid', array(), 'SonataAdminBunde');
{{ 'label.is_valid'|trans({}, 'SonataAdminBundle') }}
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
$translator->trans('label.is_valid', array(), 'SonataAdminBunde');
{{ 'label.is_valid'|trans({}, 'SonataAdminBundle') }}
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
La sobreescritura de traducciones
está relacionado con el dominio y no
con el bundle
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
WHAT?!
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
“The last translation file always wins...”
“Translation files are also not aware of
bundle inheritance...”
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
WTF?!
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
app/Resources/translations
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
app/Resources/translations
Symfony Best Practices
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
VALIDACIONES
MECANISMOS... # 6
Grupos de validación
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Grupo de Validación
class User implements UserInterface
{
/**
*
@AssertEmail(groups={"registration"})
*/
private $email;
/**
*
@AssertNotBlank(groups={"registration"})
* @AssertLength(min=7,
groups={"registration"})
*/
private $password;
/**
* @AssertValid()
*
@ORMOneToOne(targetEntity="Address"
, mappedBy="address")
*/
private $address;
/**
* @AssertLength(min=2)
*/
private $city;
}
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
class User implements UserInterface
{
/**
*
@AssertEmail(groups={"registration"})
*/
private $email;
/**
*
@AssertNotBlank(groups={"registration"})
* @AssertLength(min=7,
groups={"registration"})
*/
private $password;
/**
* @AssertValid()
*
@ORMOneToOne(targetEntity="Address"
, mappedBy="address")
*/
private $address;
/**
* @AssertLength(min=2)
*/
private $city;
}
Grupo de Validación
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
¿y cómo sobreescribimos las
validaciones?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
“Symfony loads all validation
configuration files from every bundle and
combines them into one validation
metadata tree. This means you are able
to add new constraints to a property, but
you cannot override them.”
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
“To override this, the 3rd party bundle
needs to have configuration for validation
groups.”
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Y…?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
fos_user:
registration:
form:
validation_groups: [Registration, Default]
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
<service id="fos_user.registration.form.factory"
class="FOSUserBundleFormFactoryFormFactory">
<argument type="service" id="form.factory" />
<argument>%fos_user.registration.form.name%</argument>
<argument>%fos_user.registration.form.type%</argument>
<argument>%fos_user.registration.form.validation_groups%</argument>
</service>
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
$form = $this->createFormBuilder($users, array(
'validation_groups' => array('Registration', 'Default'),
))->add(...);
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
$errors = $validator
->validate($author, null, array('Registration', 'Default'));
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
SERVICIOS
MECANISMOS... # 7
1ª Sobreescribir parámetro de la clase
del servicio
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
# app/config/config.yml
parameters:
# @FrameworkBundle/Resources/config/translation.xml
translator.class: AcmeHelloBundleTranslationTranslator
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
2ª Sobreescribiendo el servicio creando
otro con el mismo id
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
2ª Sobreescribiendo el servicio creando
otro con el mismo id
Muy mala práctica
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
3ª Usando CompilerPass
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
¿Qué es un CompilerPass?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Es el modo en que Symfony2 permite
interactuar con los servicio y parámetros
definidos globalmente y en los bundles
cuando han sido cargados, pero antes
de que se hayan compilado y
optimizados en el DependencyInjection
Component (DIC)
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
original_service_id:
class: OriginalBundleServiceClass
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
// src/Acme/DemoBundle/DependencyInjection/Compiler/OverrideServiceCompilerPass.php
namespace AcmeDemoBundleDependencyInjectionCompiler;
use SymfonyComponentDependencyInjectionCompilerCompilerPassInterface;
use SymfonyComponentDependencyInjectionContainerBuilder;
class OverrideServiceCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$definition = $container->getDefinition('original-service-id');
$definition->setClass('AcmeDemoBundleYourService');
}
}
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
FORMULARIOS
MECANISMOS... # 8
Declarado como servicio
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
services:
app.form.type.task:
class: AppBundleFormTypeTaskType
arguments: ["@app.my_service"]
tags:
- { name: form.type }
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
services:
app.form.type.task:
class: AppBundleFormTypeTaskType
arguments: ["@app.my_service"]
tags:
- { name: form.type }Como un servicio
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Herencia de Forms
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
class GenderType extends AbstractType
{
...
public function getParent()
{
return ChoiceType::class;
}
}
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
¿Si queremos que un nuevo formulario
entre dentro del comportamiento del
bundle con alguna nueva funcionalidad?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
El bundle tiene que proveer esa “lógica”
y permitir su configuración
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
¿Cómo?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
fos_user:
registration:
form:
type: FOSUserBundleFormTypeRegistrationFormType
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
<service id="fos_user.registration.form.factory"
class="FOSUserBundleFormFactoryFormFactory">
<argument type="service" id="form.factory" />
<argument>%fos_user.registration.form.name%</argument>
<argument>%fos_user.registration.form.type%</argument>
<argument>%fos_user.registration.form.validation_groups%</argument>
</service>
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Form Type Extension
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Form Type Extension
Documentación
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
¿MUCHA
INFORMACIÓN?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
¿ABURRIDO?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
¿SUEÑO?
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
TOMA AIRE ...
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
… RESPIRA ...
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
… Y PREPÁRATE ...
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
¡QUÉ VIENE LO COMPLICADO!
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
¡RELEVO!
ENTITIES &
ENTITY MAPPING
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Due to the way Doctrine works, it is not
possible to override entity mapping of a
bundle. However, if a bundle provides a
mapped superclass (such as the User entity
in the FOSUserBundle) one can override
attributes and associations. Learn more
about this feature and its limitations in the
Doctrine documentation.
http://symfony.com/doc/current/cookbook/bundles/override.html#entities-entity-mapping
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
ENTITIES & ENTITY MAPPING # 1
CONCEPTOS BASE
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
ORM:
Object-Relational Mapping
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
ORM
≠
Active Record
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Tenemos que dar doctrine la
información de “mapping”
MAPPING FORMATS
ENTITIES & ENTITY MAPPING # 2
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
XML:
<field name="name" type="string" length=100 />
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
YML:
fields:
name:
type: string
length: 100
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
PHP:
$classMetadata ->mapField(array(
'fieldName' => 'slug',
'type' => 'string',
'nullable' => true
));
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Annotations:
/**
* @ORMColumn(type="string", length=100)
*/
protected $name;
AUTOMAPPING
ENTITIES & ENTITY MAPPING # 3
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Automapping:
Busca información de mapeo:
● 1º ./Resources/config/doctrine/entityname. [xml | yml | php]
● 2º Annotation en ./Entity
En un bundle no se pueden mezclar
formatos
(annotation, xml, yml)
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Automapping:
Funciona sólo si tengo una única
conexión a BD
# Doctrine Configuration
doctrine:
dbal:
driver: "%database_driver%"
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
orm:
auto_generate_proxy_classes: "%kernel.debug%"
default_entity_manager: default
entity_managers:
default:
auto_mapping: true
mappings:
AppBundle:
type: xml
dir: SomeResources/config/doctrine
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
http://symfony.com/doc/current/reference/configuration/doctrine.html
INHERITANCE MAPPING
ENTITIES & ENTITY MAPPING # 4
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Mapped Superclass:
No es una entidad, pero participa de alguna manera en el
árbol de herencia de clases
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Mapped Superclass:
Su objetivo es definir información de mapeo que van a
heredar otras entidades
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Mapped Superclass:
<mapped-superclass name="FOSUserBundleEntityUser">
<field name="username" column="username" type="string" length="255" />
….
Table Inheritance
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Herencia de clases reflejada en base de datos
1 - Single Table Inheritance
/**
* @Entity
* @InheritanceType("SINGLE_TABLE")
* @DiscriminatorColumn(name="discr", type="string")
* @DiscriminatorMap({"person" = "Person", "employee" = "Employee"})
*/
class Person
{
// ...
}
/**
* @Entity
*/
class Employee extends Person
{
// ...
}
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
1 - Single Table Inheritance
/**
* @Entity
* @InheritanceType("SINGLE_TABLE")
* @DiscriminatorColumn(name="discr", type="string")
* @DiscriminatorMap({"person" = "Person", "employee" = "Employee"})
*/
class Person
{
// ...
}
/**
* @Entity
*/
class Employee extends Person
{
// ...
}
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
1 - Single Table Inheritance
/**
* @Entity
* @InheritanceType("SINGLE_TABLE")
* @DiscriminatorColumn(name="discr", type="string")
* @DiscriminatorMap({"person" = "Person", "employee" = "Employee"})
*/
class Person
{
// ...
}
/**
* @Entity
*/
class Employee extends Person
{
// ...
}
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
CUIDADO CON LOS CAMPOS NO NULLABLES
2 - Class Table Inheritance
/**
* @Entity
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="discr", type="string")
* @DiscriminatorMap({"person" = "Person", "employee" = "Employee"})
*/
class Person
{
// ...
}
/**
* @Entity
*/
class Employee extends Person
{
// ...
}
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
2 - Class Table Inheritance
/**
* @Entity
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="discr", type="string")
* @DiscriminatorMap({"person" = "Person", "employee" = "Employee"})
*/
class Person
{
// ...
}
/**
* @Entity
*/
class Employee extends Person
{
// ...
}
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
2 - Class Table Inheritance
/**
* @Entity
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="discr", type="string")
* @DiscriminatorMap({"person" = "Person", "employee" = "Employee"})
*/
class Person
{
// ...
}
/**
* @Entity
*/
class Employee extends Person
{
// ...
}
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
PERFORMANCE IMPACT
DYNAMIC MAPPING
ENTITIES & ENTITY MAPPING # 5
Bind mapping files and classes
#AcmeMyBundle.php
private function buildMappingCompilerPass ()
{
$arguments = array(
array( realpath (__DIR__ . '/Resources/config/doctrine-base' )),
'.orm.xml'
);
$locator = new Definition ('DoctrineCommonPersistenceMappingDriverDefaultFileLocator' , $arguments );
$driver = new Definition ('DoctrineORMMappingDriverXmlDriver' , array( $locator ));
return new DoctrineOrmMappingsPass ($driver, array(
'FullNamespace'
) , array(
'your_bundle.manager_name'
) , 'your_bundle.orm_enabled' );
}
How to Provide Model Classes for several Doctrine Implementations (link)
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Bind mapping files and classes
#AcmeMyBundle.php
private function buildMappingCompilerPass ()
{
$arguments = array(
array( realpath (__DIR__ . '/Resources/config/doctrine-base' )),
'.orm.xml'
);
$locator = new Definition ('DoctrineCommonPersistenceMappingDriverDefaultFileLocator' , $arguments );
$driver = new Definition ('DoctrineORMMappingDriverXmlDriver' , array( $locator ));
return new DoctrineOrmMappingsPass ($driver, array(
'FullNamespace'
) , array(
'your_bundle.manager_name'
) , 'your_bundle.orm_enabled' );
}
How to Provide Model Classes for several Doctrine Implementations (link)
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
loadClassMetadata event
# Acme/MyBundle/EventLister/MyMapper.php
public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
{
$classMetadata = $eventArgs->getClassMetadata();
if (null === $classMetadata->reflClass) {
return;
}
if ($this->isTimestampable($classMetadata)) {
if ($this->getClassAnalyzer()->hasMethod($classMetadata->reflClass, 'updateTimestamps')) {
$classMetadata->addLifecycleCallback('updateTimestamps', Events::prePersist);
$classMetadata->addLifecycleCallback('updateTimestamps', Events::preUpdate);
}
foreach (array('createdAt', 'updatedAt') as $field) {
if (!$classMetadata->hasField($field)) {
$classMetadata->mapField(array(
'fieldName' => $field,
'type' => $this->dbFieldType,
'nullable' => true
));
}
}
}
}
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
loadClassMetadata event
# Acme/MyBundle/EventLister/MyMapper.php
public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
{
$classMetadata = $eventArgs->getClassMetadata();
if (null === $classMetadata->reflClass) {
return;
}
if ($this->isTimestampable($classMetadata)) {
if ($this->getClassAnalyzer()->hasMethod($classMetadata->reflClass, 'updateTimestamps')) {
$classMetadata->addLifecycleCallback('updateTimestamps', Events::prePersist);
$classMetadata->addLifecycleCallback('updateTimestamps', Events::preUpdate);
}
foreach (array('createdAt', 'updatedAt') as $field) {
if (!$classMetadata->hasField($field)) {
$classMetadata->mapField(array(
'fieldName' => $field,
'type' => $this->dbFieldType,
'nullable' => true
));
}
}
}
}
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Sonata Doctrine Collector (EasyExtendsBundle)
/**
* @param array $config
*
* @throws Exception
*/
protected function addDoctrineDiscriminators(array $config)
{
$collector = DoctrineCollector::getInstance();
$purchasableClass = 'ReusableBundleEntityAbstractsAbstractPurchasable';
$collector->addDiscriminator($purchasableClass, 'PRODUCT', $config['class']['product']);
$types = $config['class']['purchasable_mapping'];
foreach ($types as $type) {
list($key, $class) = array_values($type);
if (!class_exists($class)) {
throw new Exception(sprintf('Class %s not found', $class));
}
//Add custom type
$collector->addDiscriminator($purchasableClass, $key, $class);
}
}
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Sonata Doctrine Collector (EasyExtendsBundle)
/**
* @param array $config
*
* @throws Exception
*/
protected function addDoctrineDiscriminators(array $config)
{
$collector = DoctrineCollector::getInstance();
$purchasableClass = 'ReusableBundleEntityAbstractsAbstractPurchasable';
$collector->addDiscriminator($purchasableClass, 'PRODUCT', $config['class']['product']);
$types = $config['class']['purchasable_mapping'];
foreach ($types as $type) {
list($key, $class) = array_values($type);
if (!class_exists($class)) {
throw new Exception(sprintf('Class %s not found', $class));
}
//Add custom type
$collector->addDiscriminator($purchasableClass, $key, $class);
}
}
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Relationships with abstract
classes and interfaces
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"...>
<mapped-superclass name="ReusableBundleEntityAbstractsAbstractCartLine">
<id name="id" type="integer" column="id">
<generator strategy="AUTO"/>
</id>
<field name="quantity" column="quantity" type="integer" nullable="false" />
<many-to-one target-entity="ReusableBundleEntityAbstractsAbstractPurchasable"
field="purchasable" />
<many-to-one target-entity="ReusableBundleModelInterfacesCartInterface"
inversed-by="cartLines" field="cart" />
</mapped-superclass>
</doctrine-mapping>
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Relationships with abstract
classes and interfaces
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"...>
<mapped-superclass name="ReusableBundleEntityAbstractsAbstractCartLine">
<id name="id" type="integer" column="id">
<generator strategy="AUTO"/>
</id>
<field name="quantity" column="quantity" type="integer" nullable="false" />
<many-to-one target-entity="ReusableBundleEntityAbstractsAbstractPurchasable"
field="purchasable" />
<many-to-one target-entity="ReusableBundleModelInterfacesCartInterface"
inversed-by="cartLines" field="cart" />
</mapped-superclass>
</doctrine-mapping>
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Relationships with abstract
classes and interfaces
# app/config/config.yml
doctrine:
# ...
orm:
# ...
resolve_target_entities:
AcmeReusableBundleModelInterfacesCartInterface: AcmeAppBundleEntityCart
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
PUTTING ALL TOGETHER
ENTITIES & ENTITY MAPPING # 6
Via MappedSuperClass
ENTITIES & ENTITY MAPPING # 6.1
FOSUserBundle
Sonata * Bundle
The bundle provides base classes which are already mapped for most fields to make it easier to
create your entity. Here is how you use it:
1. Extend the base User class
2. Map the id field. It must be protected as it is inherited from the parent class.
When you extend from the mapped superclass provided by the bundle, don't redefine the mapping
for the other fields as it is provided by the bundle.
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
FOSUserBundle
Sonata * Bundle
The bundle provides base classes which are already mapped for most fields to make it easier to
create your entity. Here is how you use it:
1. Extend the base User class
2. Map the id field. It must be protected as it is inherited from the parent class.
When you extend from the mapped superclass provided by the bundle, don't redefine the mapping
for the other fields as it is provided by the bundle.
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
FOSUserBundle
Sonata * Bundle
The bundle provides base classes which are already mapped for most fields to make it easier to
create your entity. Here is how you use it:
1. Extend the base User class
2. Map the id field. It must be protected as it is inherited from the parent class.
When you extend from the mapped superclass provided by the bundle, don't redefine the mapping
for the other fields as it is provided by the bundle.
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
FOSUserBundle
Sonata * Bundle
The bundle provides base classes which are already mapped for most fields to make it easier to
create your entity. Here is how you use it:
1. Extend the base User class
2. Map the id field. It must be protected as it is inherited from the parent class.
When you extend from the mapped superclass provided by the bundle, don't redefine the mapping
for the other fields as it is provided by the bundle.
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
FOSUserBundle
Sonata * Bundle
FOSUser no crea las relaciones entre
User - Group
Las deja del lado del cliente
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
via configuration
ENTITIES & ENTITY MAPPING
#
6.2
simple shopping cart
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Cart
- user
- createdAt
- ...
CartLine
- cart
- purchasable
- quantity
- ...
Purchasable
- name
- price
- ...
Product
- media
- size
- ...
Ticket
- date
- ...
Book
- isbn
- ...
DeliverableTrait
- width
- height
- weight
Estrategia
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Declarar clases abstractas y
mapearlas como mapped-super-class
Estrategia
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Declarar una interfaz para cada clase
Estrategia
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Heredar de la clase abstracta
evitando auto-mapping
Estrategia
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Hacer configurable
acme_reusable:
class:
product: AppBundleEntityProduct
cart: ...
cart_line: ...
purchasables:
ticket: { key: TICKET, class: AppBundleEntityTickets }
book: { key: BOOK, class: AppBundleEntityBook }
Estrategia
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Hacer configurable
acme_reusable:
class:
product: AppBundleEntityProduct
cart: ...
cart_line: ...
purchasables:
ticket: { key: TICKET, class: AppBundleEntityTickets }
book: { key: BOOK, class: AppBundleEntityBook }
Estrategia
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
Hacer configurable
acme_reusable:
class:
product: AppBundleEntityProduct
cart: ...
cart_line: ...
purchasables:
ticket: { key: TICKET, class: AppBundleEntityTickets }
book: { key: BOOK, class: AppBundleEntityBook }
Estrategia
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
// AcmeReusableExtension.php
protected function setConfiguration(ContainerBuilder $container, $config)
{
$container->setParameter('acme_reusable.model_manager_name', $config['model_manager_name']);
$container->setParameter('acme_reusable.orm_enabled', $config['orm_enabled']);
$this->configureClass($container, $config);
}
Estrategia
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$treeBuilder->root('acme_reusable')
->children()
->arrayNode('class')
->children()
->scalarNode('product')->cannotBeEmpty()->defaultValue(self::PRODUCT_CLASS)->end()
->scalarNode('cart')->cannotBeEmpty()->defaultValue(self::CART_CLASS)->end()
….
->arrayNode('purchasable_mapping')
->prototype('array')
->children()
->scalarNode('key')->end()
->scalarNode('class')->end()
->end()
->end()
->end()
->end()
->end()
->end()
->end();
return $treeBuilder;
}
Estrategia
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
// AcmeReusableBundle.php
private function buildOrmCompilerPass(ContainerBuilder $container)
{
$arguments = array(array(realpath(__DIR__.'/Resources/config/doctrine-model')), '.orm.xml');
$locator = new Definition('DoctrineCommonPersistenceMappingDriverDefaultFileLocator', $arguments);
$driver = new Definition('DoctrineORMMappingDriverXmlDriver', array($locator));
foreach ($this->getContainerExtension()->getEntitiesOverrides() as $configKey => $entity) {
$container->addCompilerPass(
new DoctrineOrmMappingsPass(
$driver,
array("%acme_reusable.$configKey.class%"),
array('acme_reusable.model_manager_name', 'orm'),
"acme_reusable.use_default.$configKey"
)
);
}
}
Estrategia
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
// AcmeReusableBundle.php
public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
{
$this->classMetadata = $eventArgs->getClassMetadata();
$classMetadata = $this->classMetadata;
if ($classMetadata->reflClass === $this->cartClass) {
$classMetadata->mapOneToMany(array(
'fieldName' => 'cartLines',
'targetEntity' => $this->cartLineClass,
'cascade' => array(
1 => 'all',
),
'mappedBy' => 'cart',
'orphanRemoval' => true,
));
}
}
Un ejemplo
https://github.com/gerfigna/ReusableBundle
https://github.com/gerfigna/DummyApp
CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
GRACIAS
Alfonso Machado
email@alfonsomachado.com
almacbe
Germán Figna
gfigna@gmail.com
gerfigna

More Related Content

Recently uploaded

How to write a program in any programming language
How to write a program in any programming languageHow to write a program in any programming language
How to write a program in any programming language
Rakesh Kumar R
 
316895207-SAP-Oil-and-Gas-Downstream-Training.pptx
316895207-SAP-Oil-and-Gas-Downstream-Training.pptx316895207-SAP-Oil-and-Gas-Downstream-Training.pptx
316895207-SAP-Oil-and-Gas-Downstream-Training.pptx
ssuserad3af4
 
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Julian Hyde
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
Rakesh Kumar R
 
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian CompaniesE-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
Quickdice ERP
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
Łukasz Chruściel
 
Artificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension FunctionsArtificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension Functions
Octavian Nadolu
 
Using Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query PerformanceUsing Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query Performance
Grant Fritchey
 
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
mz5nrf0n
 
在线购买加拿大英属哥伦比亚大学毕业证本科学位证书原版一模一样
在线购买加拿大英属哥伦比亚大学毕业证本科学位证书原版一模一样在线购买加拿大英属哥伦比亚大学毕业证本科学位证书原版一模一样
在线购买加拿大英属哥伦比亚大学毕业证本科学位证书原版一模一样
mz5nrf0n
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
Drona Infotech
 
How Can Hiring A Mobile App Development Company Help Your Business Grow?
How Can Hiring A Mobile App Development Company Help Your Business Grow?How Can Hiring A Mobile App Development Company Help Your Business Grow?
How Can Hiring A Mobile App Development Company Help Your Business Grow?
ToXSL Technologies
 
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, FactsALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
Green Software Development
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
Ayan Halder
 
Microservice Teams - How the cloud changes the way we work
Microservice Teams - How the cloud changes the way we workMicroservice Teams - How the cloud changes the way we work
Microservice Teams - How the cloud changes the way we work
Sven Peters
 
zOS Mainframe JES2-JES3 JCL-JECL Differences
zOS Mainframe JES2-JES3 JCL-JECL DifferenceszOS Mainframe JES2-JES3 JCL-JECL Differences
zOS Mainframe JES2-JES3 JCL-JECL Differences
YousufSait3
 
Webinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for EmbeddedWebinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for Embedded
ICS
 
8 Best Automated Android App Testing Tool and Framework in 2024.pdf
8 Best Automated Android App Testing Tool and Framework in 2024.pdf8 Best Automated Android App Testing Tool and Framework in 2024.pdf
8 Best Automated Android App Testing Tool and Framework in 2024.pdf
kalichargn70th171
 
GreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-JurisicGreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-Jurisic
Green Software Development
 
E-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet DynamicsE-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet Dynamics
Hornet Dynamics
 

Recently uploaded (20)

How to write a program in any programming language
How to write a program in any programming languageHow to write a program in any programming language
How to write a program in any programming language
 
316895207-SAP-Oil-and-Gas-Downstream-Training.pptx
316895207-SAP-Oil-and-Gas-Downstream-Training.pptx316895207-SAP-Oil-and-Gas-Downstream-Training.pptx
316895207-SAP-Oil-and-Gas-Downstream-Training.pptx
 
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
 
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian CompaniesE-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
 
Artificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension FunctionsArtificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension Functions
 
Using Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query PerformanceUsing Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query Performance
 
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
 
在线购买加拿大英属哥伦比亚大学毕业证本科学位证书原版一模一样
在线购买加拿大英属哥伦比亚大学毕业证本科学位证书原版一模一样在线购买加拿大英属哥伦比亚大学毕业证本科学位证书原版一模一样
在线购买加拿大英属哥伦比亚大学毕业证本科学位证书原版一模一样
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
 
How Can Hiring A Mobile App Development Company Help Your Business Grow?
How Can Hiring A Mobile App Development Company Help Your Business Grow?How Can Hiring A Mobile App Development Company Help Your Business Grow?
How Can Hiring A Mobile App Development Company Help Your Business Grow?
 
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, FactsALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
 
Microservice Teams - How the cloud changes the way we work
Microservice Teams - How the cloud changes the way we workMicroservice Teams - How the cloud changes the way we work
Microservice Teams - How the cloud changes the way we work
 
zOS Mainframe JES2-JES3 JCL-JECL Differences
zOS Mainframe JES2-JES3 JCL-JECL DifferenceszOS Mainframe JES2-JES3 JCL-JECL Differences
zOS Mainframe JES2-JES3 JCL-JECL Differences
 
Webinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for EmbeddedWebinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for Embedded
 
8 Best Automated Android App Testing Tool and Framework in 2024.pdf
8 Best Automated Android App Testing Tool and Framework in 2024.pdf8 Best Automated Android App Testing Tool and Framework in 2024.pdf
8 Best Automated Android App Testing Tool and Framework in 2024.pdf
 
GreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-JurisicGreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-Jurisic
 
E-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet DynamicsE-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet Dynamics
 

Featured

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot
Marius Sescu
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPT
Expeed Software
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
Pixeldarts
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
ThinkNow
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
marketingartwork
 
Skeleton Culture Code
Skeleton Culture CodeSkeleton Culture Code
Skeleton Culture Code
Skeleton Technologies
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
Neil Kimberley
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
contently
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
Albert Qian
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
Kurio // The Social Media Age(ncy)
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
Search Engine Journal
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
SpeakerHub
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
Tessa Mero
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Lily Ray
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
Rajiv Jayarajah, MAppComm, ACC
 
Introduction to Data Science
Introduction to Data ScienceIntroduction to Data Science
Introduction to Data Science
Christy Abraham Joy
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best Practices
Vit Horky
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project management
MindGenius
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
RachelPearson36
 

Featured (20)

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPT
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
 
Skeleton Culture Code
Skeleton Culture CodeSkeleton Culture Code
Skeleton Culture Code
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
 
Introduction to Data Science
Introduction to Data ScienceIntroduction to Data Science
Introduction to Data Science
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best Practices
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project management
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
 

Cómo crear Third party bundles de Symfony completamente extensibles y sobreescribibles

  • 1. C THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES.
  • 2. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES gerfignaedytebfodavegmiguelvilata araquemario almacbe frankey90 driera_comraulo79
  • 3. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES wolfwolker JL_Laso araquemario almacbe frankey90 driera_comraulo79 gerfignaedytebfodavegmiguelvilata paolacaracola
  • 4. BEST PRACTICES FOR REUSABLE BUNDLES CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 5. BEST PRACTICE # 1 NOMBRE DE LOS BUNDLES
  • 6. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES AcmeBlogBundle
  • 7. AcmeBlogBundle CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 8. AcmeBundleBlogBundle CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 9. AcmeBlogBundle CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 10. PSR4 Vendor(Category)*BundleName ~ Bundle CamelCase Descriptivo y corto No más de dos palabras NOMBRE DE LOS BUNDLES: CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 11. BEST PRACTICE # 2 ESTRUCTURA DE DIRECTORIOS
  • 12. ¿Qué ficheros y carpetas son obligados? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 13. AcmeBlogBundle.php README.(md | rst) LICENSE Resources/doc/index.rst ESTRUCTURA DE LOS DIRECTORIOS: CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 14. Commands → Command/ Controllers → Controller/ Service Container Extensions → DependencyInjection/ Model classes → Model/ Configuration → Resources/config/ Web Resources (CSS, JS, images) → Resources/public/ Translation files → Resources/translations/ Templates → Resources/views/ Unit and Functional Tests → Tests/ CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES ESTRUCTURA DE LOS DIRECTORIOS:
  • 15. ¿Cómo se tiene que llamar la carpeta donde estén los Listeners y/o Subscribers? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 16. EventListener CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 17. El directorio de un bundle es de solo lectura CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 18. Y si tu bundle necesita generar algún fichero, ¿dónde lo crearías? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 19. Solo si formarán parte del repositorio... CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 20. app/logs o app/cache CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 22. ContentController.php del Bundle AcmeBlogBundle ¿directorio? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 23. Acme/BlogBundle/Controller/ContentController.php CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 24. ContentController.php del Bundle AcmeBlogBundle ¿FQC? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 25. AcmeBlogBundleControllerContentController CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 27. class FooBar { const SOMECONST = 42; /** * @var string */ private $foo_bar; private function transformText($dummy, array $options = array()) { $defaultOptions = [ 'some_default' => 'values', 'another_default' => 'more values' ]; foreach ($options as $option) { if (!in_array($option, $defaultOptions)) { throw new RuntimeException(sprintf('Unrecognized option "%s"', $option)); } } $mergedOptions = array_merge($defaultOptions, $options ); if (true === $dummy) { return; } if ($dummy === 'string') { if ('values' === $mergedOptions['some_default']) { return substr($dummy, 0, 5); } return ucwords($dummy); } } }
  • 28. class FooBar { const SOMECONST = 42; /** * @var string */ private $foo_bar; private function transformText($dummy, array $options = array()) { $defaultOptions = [ 'some_default' => 'values', 'another_default' => 'more values' ]; foreach ($options as $option) { if (!in_array($option, $defaultOptions)) { throw new RuntimeException(sprintf('Unrecognized option "%s"', $option)); } } $mergedOptions = array_merge($defaultOptions, $options ); if (true === $dummy) { return; } if ($dummy === 'string') { if ('values' === $mergedOptions['some_default']) { return substr($dummy, 0, 5); } return ucwords($dummy); } } }
  • 29. Sufijo Listener si escucha a algún evento CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 30. Clases Exception deben de ir en un sub-space Exception CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 32. PHPUnit Tests/ Los test funcionales solo deben testear la response y la información de profiling si creas alguna. No puede existir un test que sea AllTest.php Tiene que haber un phpunit.xml.dist TESTS CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 33. ¿Cuánto % de cobertura tiene que haber? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 34. >= 95% CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 36. PHPDoc. reStructuredText en Resources/doc/ DOCUMENTACIÓN: CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 37. INSTRUCCIONES DE INSTALACIÓN README.md Step 1: Download the Bundle --------------------------- composer require blabla/blabla Step 2: Enable the Bundle ------------------------- Step 3, Step 4, etc. otros requisitos como registrar rutas... CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 39. ¿Alias de AcmeBlogBundle? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 40. acme_blog CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 41. Todas las rutas tiene que tener el alias como prefijo CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 43. ¿formato recomendado yml, xliff, po ...? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 44. XLIFF CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 45. XLIFF Symfony Best Practices CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 46. ¿Nombre del dominio de las traducciones para AcmeBlogBundle? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 47. acme_blog_domain CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 48. Un bundle NO tiene que sobreescribir otros dominios de traducción CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 49. Un bundle NO tiene que sobreescribir otros dominios de traducción Symfony Best Practices CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 51. Parámetros CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 52. # app/config/config.yml parameters: # @FrameworkBundle/Resources/config/translation.xml translator.class: AcmeHelloBundleTranslationTranslator CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 53. Semantic bundle configuration CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 54. # app/config/config.yml acme_social: twitter: client_id: 123 client_secret: $ecret CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 55. // src/Acme/SocialBundle/DependencyInjection/Configuration.php namespace AcmeSocialBundleDependencyInjection; use SymfonyComponentConfigDefinitionBuilderTreeBuilder; use SymfonyComponentConfigDefinitionConfigurationInterface; class Configuration implements ConfigurationInterface { public function getConfigTreeBuilder() { $treeBuilder = new TreeBuilder(); $rootNode = $treeBuilder->root('acme_social'); $rootNode ->children() ->arrayNode('twitter') ->children() ->integerNode('client_id')-> defaultValue(123123)->end() ->scalarNode('client_secret')-> defaultValue('k453jhdaj492')->end() ->end() ->end() // twitter ->end() ; return $treeBuilder; } }
  • 56. // src/Acme/SocialBundle/DependencyInjection/Configuration.php namespace AcmeSocialBundleDependencyInjection; use SymfonyComponentConfigDefinitionBuilderTreeBuilder; use SymfonyComponentConfigDefinitionConfigurationInterface; class Configuration implements ConfigurationInterface { public function getConfigTreeBuilder() { $treeBuilder = new TreeBuilder(); $rootNode = $treeBuilder->root('acme_social'); $rootNode ->children() ->arrayNode('twitter') ->children() ->integerNode('client_id')-> defaultValue(123123)->end() ->scalarNode('client_secret')-> defaultValue('k453jhdaj492')->end() ->end() ->end() // twitter ->end() ; return $treeBuilder; } }
  • 58. Semantic Versioning Standard. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 59. MAJOR.MINOR.PATCH CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 60. ¿Qué implicaciones tiene estar en la versión 0.x.x? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 61. “4 - Major version zero (0.y.z) is for initial development. Anything may change at any time. The public API should not be considered stable.” CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 63. ¿Cómo tiene que ser el id de los servicios? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 64. bundle_alias.service_id CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 65. ¿Qué hacemos con los servicios que no son usados por la aplicación si no internamente en el bundle? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 66. services: foo: class: ExampleFoo public: false CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 67. ¿Qué implica que un servicio sea privado? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 68. No se puede hacer: $container->get('foo'); Solo se puede inyectar en otro servicio en su definición. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 69. ¿Cómo vamos hasta aquí? ¿bien? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 70. MECANISMOS DE SOBRE- ESCRITURA Y HERENCIA CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 72. ¿Cómo hacemos que un bundle herede de otro? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 73. Bundles <?php use SymfonyComponentHttpKernelBundleBundle; class UserBundle extends Bundle { public function getParent() { return 'FOSUserBundle'; } } CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 74. ¿Qué implica esto? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 75. Poder sobreescribir casi cualquier archivo del bundle padre creándolo en el mismo sitio que el padre. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 77. ¿Cómo sobreescribimos el comportamiento de un controlador? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 78. Controladores // src/UserBundle/Controller/RegistrationController.php namespace UserBundleController; use FOSUserBundleControllerRegistrationController as BaseController; class RegistrationController extends BaseController { public function registerAction() { $response = parent::registerAction(); // ... do custom stuff return $response; } } CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 79. Controladores // src/UserBundle/Controller/RegistrationController.php namespace UserBundleController; use FOSUserBundleControllerRegistrationController as BaseController; class RegistrationController extends BaseController { public function registerAction() { $response = parent::registerAction(); // ... do custom stuff return $response; } } CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 80. ¿Siempre que una ruta apunte a ese action de ese controlador se llamará al sobreescrito? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 81. route_id: path: /register defaults: { _controller: FOSUserBundle:Registration:register } CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 82. ¿De qué otra forma se puede hacer referencia a un controlador? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 83. UserBundleControllerRegistrationController::registerAction CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 84. route_id: path: /register defaults: { _controller: UserBundleControllerRegistrationController::registerAction } CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 85. ¿y otra forma? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 86. ¿se podría declarar como servicio un controlador? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 87. services: fos_user.registration_controller: class: FOSUserBundleControllerRegistrationController ... CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 88. route_id: path: /register defaults: { _controller: fos_user.registration_controller:registerAction } CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 89. route_id: path: /register defaults: { _controller: fos_user.registration_controller:registerAction } Sí, pero de otra forma. Más adelante! CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 90. Por tanto, solo se sobreescribirá si se usa ¿cómo? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 91. FOSUserBundle:Registration:register CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 92. FOSUserBundle:Registration:register CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 94. ¿Cómo “encuentra” Symfony2 los templates twig? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 95. ::index.html.twig CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 96. AcmeBlogBundle::index.html.twig CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 97. AcmeBlogBundle:Blog:index.html.twig CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 98. Orden de búsqueda 1. app/Resources/AcmeBlogBundle/views/layout.html.twig 2. src/Acme/BlogBundle/Resources/views/layout.html.twig 3. src/MyAcmeBlogBundle/Resources/views/layout.html.twig - si fuera un bundle de vendors que hemos sobreescrito. public function Bundle::getParent ( return ‘AcmeBlogBundle’; ) 4. vendor/Acme/src/BlogBundle/Resources/views/layout.html.twig - si fuera un bundle de vendors. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 99. ¿Qué dice Symfony Best Practices sobre dónde tienen que ir los templates del proyecto? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 100. app/Resources CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 101. ¿por qué? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 103. “Routing is never automatically imported in Symfony. If you want to include the routes from any bundle, then they must be manually imported from somewhere in your application (e.g. app/config/routing.yml).” CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 104. “Routing is never automatically imported in Symfony. If you want to include the routes from any bundle, then they must be manually imported from somewhere in your application (e.g. app/config/routing.yml).” Symfony Best Practices CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 105. “Copiar” las rutas del bundle y solo importar y/o modificar las que se deseen. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 107. ¿Qué son los dominios de las traducciones? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 108. $translator->trans('Symfony is great'); CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 109. ¿Cuál es el dominio de esa traducción? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 110. messages.{lang}.{yml|po|xliff} CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 111. ¿Cómo se selecciona el dominio en el translator? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 112. $translator->trans('label.is_valid', array(), 'SonataAdminBunde'); {{ 'label.is_valid'|trans({}, 'SonataAdminBundle') }} CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 113. $translator->trans('label.is_valid', array(), 'SonataAdminBunde'); {{ 'label.is_valid'|trans({}, 'SonataAdminBundle') }} CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 114. La sobreescritura de traducciones está relacionado con el dominio y no con el bundle CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 115. WHAT?! CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 116. “The last translation file always wins...” “Translation files are also not aware of bundle inheritance...” CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 117. WTF?! CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 118. app/Resources/translations CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 119. app/Resources/translations Symfony Best Practices CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 121. Grupos de validación CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 122. Grupo de Validación class User implements UserInterface { /** * @AssertEmail(groups={"registration"}) */ private $email; /** * @AssertNotBlank(groups={"registration"}) * @AssertLength(min=7, groups={"registration"}) */ private $password; /** * @AssertValid() * @ORMOneToOne(targetEntity="Address" , mappedBy="address") */ private $address; /** * @AssertLength(min=2) */ private $city; } CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 123. class User implements UserInterface { /** * @AssertEmail(groups={"registration"}) */ private $email; /** * @AssertNotBlank(groups={"registration"}) * @AssertLength(min=7, groups={"registration"}) */ private $password; /** * @AssertValid() * @ORMOneToOne(targetEntity="Address" , mappedBy="address") */ private $address; /** * @AssertLength(min=2) */ private $city; } Grupo de Validación CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 124. ¿y cómo sobreescribimos las validaciones? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 125. “Symfony loads all validation configuration files from every bundle and combines them into one validation metadata tree. This means you are able to add new constraints to a property, but you cannot override them.” CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 126. “To override this, the 3rd party bundle needs to have configuration for validation groups.” CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 127. Y…? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 128. fos_user: registration: form: validation_groups: [Registration, Default] CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 129. <service id="fos_user.registration.form.factory" class="FOSUserBundleFormFactoryFormFactory"> <argument type="service" id="form.factory" /> <argument>%fos_user.registration.form.name%</argument> <argument>%fos_user.registration.form.type%</argument> <argument>%fos_user.registration.form.validation_groups%</argument> </service> CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 130. $form = $this->createFormBuilder($users, array( 'validation_groups' => array('Registration', 'Default'), ))->add(...); CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 131. $errors = $validator ->validate($author, null, array('Registration', 'Default')); CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 133. 1ª Sobreescribir parámetro de la clase del servicio CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 134. # app/config/config.yml parameters: # @FrameworkBundle/Resources/config/translation.xml translator.class: AcmeHelloBundleTranslationTranslator CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 135. 2ª Sobreescribiendo el servicio creando otro con el mismo id CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 136. 2ª Sobreescribiendo el servicio creando otro con el mismo id Muy mala práctica CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 137. 3ª Usando CompilerPass CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 138. ¿Qué es un CompilerPass? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 139. Es el modo en que Symfony2 permite interactuar con los servicio y parámetros definidos globalmente y en los bundles cuando han sido cargados, pero antes de que se hayan compilado y optimizados en el DependencyInjection Component (DIC) CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 140. original_service_id: class: OriginalBundleServiceClass CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 141. // src/Acme/DemoBundle/DependencyInjection/Compiler/OverrideServiceCompilerPass.php namespace AcmeDemoBundleDependencyInjectionCompiler; use SymfonyComponentDependencyInjectionCompilerCompilerPassInterface; use SymfonyComponentDependencyInjectionContainerBuilder; class OverrideServiceCompilerPass implements CompilerPassInterface { public function process(ContainerBuilder $container) { $definition = $container->getDefinition('original-service-id'); $definition->setClass('AcmeDemoBundleYourService'); } } CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 143. Declarado como servicio CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 144. services: app.form.type.task: class: AppBundleFormTypeTaskType arguments: ["@app.my_service"] tags: - { name: form.type } CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 145. services: app.form.type.task: class: AppBundleFormTypeTaskType arguments: ["@app.my_service"] tags: - { name: form.type }Como un servicio CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 146. Herencia de Forms CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 147. class GenderType extends AbstractType { ... public function getParent() { return ChoiceType::class; } } CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 148. ¿Si queremos que un nuevo formulario entre dentro del comportamiento del bundle con alguna nueva funcionalidad? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 149. El bundle tiene que proveer esa “lógica” y permitir su configuración CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 150. ¿Cómo? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 151. fos_user: registration: form: type: FOSUserBundleFormTypeRegistrationFormType CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 152. <service id="fos_user.registration.form.factory" class="FOSUserBundleFormFactoryFormFactory"> <argument type="service" id="form.factory" /> <argument>%fos_user.registration.form.name%</argument> <argument>%fos_user.registration.form.type%</argument> <argument>%fos_user.registration.form.validation_groups%</argument> </service> CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 153. Form Type Extension CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 154. Form Type Extension Documentación CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 155. ¿MUCHA INFORMACIÓN? CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 156. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES ¿ABURRIDO?
  • 157. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES ¿SUEÑO?
  • 158. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES TOMA AIRE ...
  • 159. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES … RESPIRA ...
  • 160. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES … Y PREPÁRATE ...
  • 161. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES ¡QUÉ VIENE LO COMPLICADO!
  • 162. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES ¡RELEVO!
  • 163. ENTITIES & ENTITY MAPPING CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 164. Due to the way Doctrine works, it is not possible to override entity mapping of a bundle. However, if a bundle provides a mapped superclass (such as the User entity in the FOSUserBundle) one can override attributes and associations. Learn more about this feature and its limitations in the Doctrine documentation. http://symfony.com/doc/current/cookbook/bundles/override.html#entities-entity-mapping CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 165. ENTITIES & ENTITY MAPPING # 1 CONCEPTOS BASE
  • 166. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES ORM: Object-Relational Mapping
  • 167. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES ORM ≠ Active Record
  • 168. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 169. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 170. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES Tenemos que dar doctrine la información de “mapping”
  • 171. MAPPING FORMATS ENTITIES & ENTITY MAPPING # 2
  • 172. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES XML: <field name="name" type="string" length=100 />
  • 173. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES YML: fields: name: type: string length: 100
  • 174. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES PHP: $classMetadata ->mapField(array( 'fieldName' => 'slug', 'type' => 'string', 'nullable' => true ));
  • 175. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES Annotations: /** * @ORMColumn(type="string", length=100) */ protected $name;
  • 177. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES Automapping: Busca información de mapeo: ● 1º ./Resources/config/doctrine/entityname. [xml | yml | php] ● 2º Annotation en ./Entity
  • 178. En un bundle no se pueden mezclar formatos (annotation, xml, yml) CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 179. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES Automapping: Funciona sólo si tengo una única conexión a BD
  • 180. # Doctrine Configuration doctrine: dbal: driver: "%database_driver%" host: "%database_host%" port: "%database_port%" dbname: "%database_name%" user: "%database_user%" password: "%database_password%" charset: UTF8 orm: auto_generate_proxy_classes: "%kernel.debug%" default_entity_manager: default entity_managers: default: auto_mapping: true mappings: AppBundle: type: xml dir: SomeResources/config/doctrine CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES http://symfony.com/doc/current/reference/configuration/doctrine.html
  • 181. INHERITANCE MAPPING ENTITIES & ENTITY MAPPING # 4
  • 182. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES Mapped Superclass: No es una entidad, pero participa de alguna manera en el árbol de herencia de clases
  • 183. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES Mapped Superclass: Su objetivo es definir información de mapeo que van a heredar otras entidades
  • 184. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES Mapped Superclass: <mapped-superclass name="FOSUserBundleEntityUser"> <field name="username" column="username" type="string" length="255" /> ….
  • 185. Table Inheritance CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES Herencia de clases reflejada en base de datos
  • 186. 1 - Single Table Inheritance /** * @Entity * @InheritanceType("SINGLE_TABLE") * @DiscriminatorColumn(name="discr", type="string") * @DiscriminatorMap({"person" = "Person", "employee" = "Employee"}) */ class Person { // ... } /** * @Entity */ class Employee extends Person { // ... } CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 187. 1 - Single Table Inheritance /** * @Entity * @InheritanceType("SINGLE_TABLE") * @DiscriminatorColumn(name="discr", type="string") * @DiscriminatorMap({"person" = "Person", "employee" = "Employee"}) */ class Person { // ... } /** * @Entity */ class Employee extends Person { // ... } CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 188. 1 - Single Table Inheritance /** * @Entity * @InheritanceType("SINGLE_TABLE") * @DiscriminatorColumn(name="discr", type="string") * @DiscriminatorMap({"person" = "Person", "employee" = "Employee"}) */ class Person { // ... } /** * @Entity */ class Employee extends Person { // ... } CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES CUIDADO CON LOS CAMPOS NO NULLABLES
  • 189. 2 - Class Table Inheritance /** * @Entity * @InheritanceType("JOINED") * @DiscriminatorColumn(name="discr", type="string") * @DiscriminatorMap({"person" = "Person", "employee" = "Employee"}) */ class Person { // ... } /** * @Entity */ class Employee extends Person { // ... } CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 190. 2 - Class Table Inheritance /** * @Entity * @InheritanceType("JOINED") * @DiscriminatorColumn(name="discr", type="string") * @DiscriminatorMap({"person" = "Person", "employee" = "Employee"}) */ class Person { // ... } /** * @Entity */ class Employee extends Person { // ... } CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 191. 2 - Class Table Inheritance /** * @Entity * @InheritanceType("JOINED") * @DiscriminatorColumn(name="discr", type="string") * @DiscriminatorMap({"person" = "Person", "employee" = "Employee"}) */ class Person { // ... } /** * @Entity */ class Employee extends Person { // ... } CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES PERFORMANCE IMPACT
  • 192. DYNAMIC MAPPING ENTITIES & ENTITY MAPPING # 5
  • 193. Bind mapping files and classes #AcmeMyBundle.php private function buildMappingCompilerPass () { $arguments = array( array( realpath (__DIR__ . '/Resources/config/doctrine-base' )), '.orm.xml' ); $locator = new Definition ('DoctrineCommonPersistenceMappingDriverDefaultFileLocator' , $arguments ); $driver = new Definition ('DoctrineORMMappingDriverXmlDriver' , array( $locator )); return new DoctrineOrmMappingsPass ($driver, array( 'FullNamespace' ) , array( 'your_bundle.manager_name' ) , 'your_bundle.orm_enabled' ); } How to Provide Model Classes for several Doctrine Implementations (link) CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 194. Bind mapping files and classes #AcmeMyBundle.php private function buildMappingCompilerPass () { $arguments = array( array( realpath (__DIR__ . '/Resources/config/doctrine-base' )), '.orm.xml' ); $locator = new Definition ('DoctrineCommonPersistenceMappingDriverDefaultFileLocator' , $arguments ); $driver = new Definition ('DoctrineORMMappingDriverXmlDriver' , array( $locator )); return new DoctrineOrmMappingsPass ($driver, array( 'FullNamespace' ) , array( 'your_bundle.manager_name' ) , 'your_bundle.orm_enabled' ); } How to Provide Model Classes for several Doctrine Implementations (link) CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 195. loadClassMetadata event # Acme/MyBundle/EventLister/MyMapper.php public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs) { $classMetadata = $eventArgs->getClassMetadata(); if (null === $classMetadata->reflClass) { return; } if ($this->isTimestampable($classMetadata)) { if ($this->getClassAnalyzer()->hasMethod($classMetadata->reflClass, 'updateTimestamps')) { $classMetadata->addLifecycleCallback('updateTimestamps', Events::prePersist); $classMetadata->addLifecycleCallback('updateTimestamps', Events::preUpdate); } foreach (array('createdAt', 'updatedAt') as $field) { if (!$classMetadata->hasField($field)) { $classMetadata->mapField(array( 'fieldName' => $field, 'type' => $this->dbFieldType, 'nullable' => true )); } } } } CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 196. loadClassMetadata event # Acme/MyBundle/EventLister/MyMapper.php public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs) { $classMetadata = $eventArgs->getClassMetadata(); if (null === $classMetadata->reflClass) { return; } if ($this->isTimestampable($classMetadata)) { if ($this->getClassAnalyzer()->hasMethod($classMetadata->reflClass, 'updateTimestamps')) { $classMetadata->addLifecycleCallback('updateTimestamps', Events::prePersist); $classMetadata->addLifecycleCallback('updateTimestamps', Events::preUpdate); } foreach (array('createdAt', 'updatedAt') as $field) { if (!$classMetadata->hasField($field)) { $classMetadata->mapField(array( 'fieldName' => $field, 'type' => $this->dbFieldType, 'nullable' => true )); } } } } CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 197. Sonata Doctrine Collector (EasyExtendsBundle) /** * @param array $config * * @throws Exception */ protected function addDoctrineDiscriminators(array $config) { $collector = DoctrineCollector::getInstance(); $purchasableClass = 'ReusableBundleEntityAbstractsAbstractPurchasable'; $collector->addDiscriminator($purchasableClass, 'PRODUCT', $config['class']['product']); $types = $config['class']['purchasable_mapping']; foreach ($types as $type) { list($key, $class) = array_values($type); if (!class_exists($class)) { throw new Exception(sprintf('Class %s not found', $class)); } //Add custom type $collector->addDiscriminator($purchasableClass, $key, $class); } } CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 198. Sonata Doctrine Collector (EasyExtendsBundle) /** * @param array $config * * @throws Exception */ protected function addDoctrineDiscriminators(array $config) { $collector = DoctrineCollector::getInstance(); $purchasableClass = 'ReusableBundleEntityAbstractsAbstractPurchasable'; $collector->addDiscriminator($purchasableClass, 'PRODUCT', $config['class']['product']); $types = $config['class']['purchasable_mapping']; foreach ($types as $type) { list($key, $class) = array_values($type); if (!class_exists($class)) { throw new Exception(sprintf('Class %s not found', $class)); } //Add custom type $collector->addDiscriminator($purchasableClass, $key, $class); } } CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 199. Relationships with abstract classes and interfaces <?xml version="1.0" encoding="UTF-8"?> <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"...> <mapped-superclass name="ReusableBundleEntityAbstractsAbstractCartLine"> <id name="id" type="integer" column="id"> <generator strategy="AUTO"/> </id> <field name="quantity" column="quantity" type="integer" nullable="false" /> <many-to-one target-entity="ReusableBundleEntityAbstractsAbstractPurchasable" field="purchasable" /> <many-to-one target-entity="ReusableBundleModelInterfacesCartInterface" inversed-by="cartLines" field="cart" /> </mapped-superclass> </doctrine-mapping> CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 200. Relationships with abstract classes and interfaces <?xml version="1.0" encoding="UTF-8"?> <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"...> <mapped-superclass name="ReusableBundleEntityAbstractsAbstractCartLine"> <id name="id" type="integer" column="id"> <generator strategy="AUTO"/> </id> <field name="quantity" column="quantity" type="integer" nullable="false" /> <many-to-one target-entity="ReusableBundleEntityAbstractsAbstractPurchasable" field="purchasable" /> <many-to-one target-entity="ReusableBundleModelInterfacesCartInterface" inversed-by="cartLines" field="cart" /> </mapped-superclass> </doctrine-mapping> CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 201. Relationships with abstract classes and interfaces # app/config/config.yml doctrine: # ... orm: # ... resolve_target_entities: AcmeReusableBundleModelInterfacesCartInterface: AcmeAppBundleEntityCart CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 202. PUTTING ALL TOGETHER ENTITIES & ENTITY MAPPING # 6
  • 203. Via MappedSuperClass ENTITIES & ENTITY MAPPING # 6.1
  • 204. FOSUserBundle Sonata * Bundle The bundle provides base classes which are already mapped for most fields to make it easier to create your entity. Here is how you use it: 1. Extend the base User class 2. Map the id field. It must be protected as it is inherited from the parent class. When you extend from the mapped superclass provided by the bundle, don't redefine the mapping for the other fields as it is provided by the bundle. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 205. FOSUserBundle Sonata * Bundle The bundle provides base classes which are already mapped for most fields to make it easier to create your entity. Here is how you use it: 1. Extend the base User class 2. Map the id field. It must be protected as it is inherited from the parent class. When you extend from the mapped superclass provided by the bundle, don't redefine the mapping for the other fields as it is provided by the bundle. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 206. FOSUserBundle Sonata * Bundle The bundle provides base classes which are already mapped for most fields to make it easier to create your entity. Here is how you use it: 1. Extend the base User class 2. Map the id field. It must be protected as it is inherited from the parent class. When you extend from the mapped superclass provided by the bundle, don't redefine the mapping for the other fields as it is provided by the bundle. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 207. FOSUserBundle Sonata * Bundle The bundle provides base classes which are already mapped for most fields to make it easier to create your entity. Here is how you use it: 1. Extend the base User class 2. Map the id field. It must be protected as it is inherited from the parent class. When you extend from the mapped superclass provided by the bundle, don't redefine the mapping for the other fields as it is provided by the bundle. CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 208. FOSUserBundle Sonata * Bundle FOSUser no crea las relaciones entre User - Group Las deja del lado del cliente CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES
  • 209. via configuration ENTITIES & ENTITY MAPPING # 6.2
  • 210. simple shopping cart CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES Cart - user - createdAt - ... CartLine - cart - purchasable - quantity - ... Purchasable - name - price - ... Product - media - size - ... Ticket - date - ... Book - isbn - ... DeliverableTrait - width - height - weight
  • 211. Estrategia CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES Declarar clases abstractas y mapearlas como mapped-super-class
  • 212. Estrategia CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES Declarar una interfaz para cada clase
  • 213. Estrategia CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES Heredar de la clase abstracta evitando auto-mapping
  • 214. Estrategia CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES Hacer configurable acme_reusable: class: product: AppBundleEntityProduct cart: ... cart_line: ... purchasables: ticket: { key: TICKET, class: AppBundleEntityTickets } book: { key: BOOK, class: AppBundleEntityBook }
  • 215. Estrategia CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES Hacer configurable acme_reusable: class: product: AppBundleEntityProduct cart: ... cart_line: ... purchasables: ticket: { key: TICKET, class: AppBundleEntityTickets } book: { key: BOOK, class: AppBundleEntityBook }
  • 216. Estrategia CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES Hacer configurable acme_reusable: class: product: AppBundleEntityProduct cart: ... cart_line: ... purchasables: ticket: { key: TICKET, class: AppBundleEntityTickets } book: { key: BOOK, class: AppBundleEntityBook }
  • 217. Estrategia CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES // AcmeReusableExtension.php protected function setConfiguration(ContainerBuilder $container, $config) { $container->setParameter('acme_reusable.model_manager_name', $config['model_manager_name']); $container->setParameter('acme_reusable.orm_enabled', $config['orm_enabled']); $this->configureClass($container, $config); }
  • 218. Estrategia CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES public function getConfigTreeBuilder() { $treeBuilder = new TreeBuilder(); $treeBuilder->root('acme_reusable') ->children() ->arrayNode('class') ->children() ->scalarNode('product')->cannotBeEmpty()->defaultValue(self::PRODUCT_CLASS)->end() ->scalarNode('cart')->cannotBeEmpty()->defaultValue(self::CART_CLASS)->end() …. ->arrayNode('purchasable_mapping') ->prototype('array') ->children() ->scalarNode('key')->end() ->scalarNode('class')->end() ->end() ->end() ->end() ->end() ->end() ->end() ->end(); return $treeBuilder; }
  • 219. Estrategia CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES // AcmeReusableBundle.php private function buildOrmCompilerPass(ContainerBuilder $container) { $arguments = array(array(realpath(__DIR__.'/Resources/config/doctrine-model')), '.orm.xml'); $locator = new Definition('DoctrineCommonPersistenceMappingDriverDefaultFileLocator', $arguments); $driver = new Definition('DoctrineORMMappingDriverXmlDriver', array($locator)); foreach ($this->getContainerExtension()->getEntitiesOverrides() as $configKey => $entity) { $container->addCompilerPass( new DoctrineOrmMappingsPass( $driver, array("%acme_reusable.$configKey.class%"), array('acme_reusable.model_manager_name', 'orm'), "acme_reusable.use_default.$configKey" ) ); } }
  • 220. Estrategia CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES // AcmeReusableBundle.php public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs) { $this->classMetadata = $eventArgs->getClassMetadata(); $classMetadata = $this->classMetadata; if ($classMetadata->reflClass === $this->cartClass) { $classMetadata->mapOneToMany(array( 'fieldName' => 'cartLines', 'targetEntity' => $this->cartLineClass, 'cascade' => array( 1 => 'all', ), 'mappedBy' => 'cart', 'orphanRemoval' => true, )); } }
  • 221. Un ejemplo https://github.com/gerfigna/ReusableBundle https://github.com/gerfigna/DummyApp CÓMO CREAR THIRD PARTY BUNDLES DE SYMFONY COMPLETAMENTE EXTENSIBLES Y SOBREESCRIBIBLES