Materiales del curso de Symfony2
-
Upload
raul-fraile -
Category
Technology
-
view
2.597 -
download
4
description
Transcript of Materiales del curso de Symfony2
![Page 1: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/1.jpg)
Raúl Fraile Beneyto
Materiales del curso
![Page 2: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/2.jpg)
Temario
• Tema 1: Prerequisitos
• PHP 5.3
• YAML
• MVC
• PSR-0 (Autoloading)
• PSR-1, PSR-2 (Coding Standards)
![Page 3: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/3.jpg)
Temario
• Tema 2: Introducción a symfony2
• Historia
• Arquitectura
• Gestión de dependencias con Composer
• Inyección de dependencias
• Entornos de ejecución
• Instalación y configuración
• Documentación
![Page 4: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/4.jpg)
Temario
• Tema 3: Primeras páginas
• Bundles
• Routing
• Controladores
![Page 5: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/5.jpg)
Temario
• Tema 4: Lenguaje de plantillas Twig
• Sintaxis básica
• Herencia
• Macros
• Twig extensions
![Page 6: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/6.jpg)
Temario
• Tema 5: Bases de datos con Doctrine2
• ORM
• DBAL
• Entidades y relaciones
• Configuración
• Fixtures
![Page 7: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/7.jpg)
Temario
• Tema 6: Frontend
• Gestión de assets
• Tratamiento de imágenes
• Formatos alternativos
![Page 8: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/8.jpg)
Temario
• Tema 7: Backend
• Formularios
• Conceptos básicos
• Generación automática de formularios
• Formularios avanzados
• Validación
![Page 9: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/9.jpg)
Temario
• Tema 8: Seguridad
• Autenticación VS Autorización
• Roles
• Configuración
• Login
![Page 10: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/10.jpg)
Temario
• Tema 9: Servicios y eventos
• Contenedor de inyección de dependencias
• Eventos
![Page 11: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/11.jpg)
Temario
• Tema 10: Extendiendo symfony2
• Comandos de consola
• Extensiones propias de Twig
![Page 12: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/12.jpg)
Temario
• Tema 11: Optimización y rendimiento
• Optimización de assets
• APC
• ESI
![Page 13: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/13.jpg)
Temario
• Proyecto: tienda “social” de libros
• Usuarios se registran y compran libros. Tienen un perfil público con los libros comprados.
• Los libros se agrupan por tecnologías (N:M).
• Backend para gestionar usuarios, libros y tecnologías.
• Multiidioma, optimización de assets, redimensión imágenes, canales RSS, etc.
![Page 14: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/14.jpg)
Prerequisitos
![Page 15: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/15.jpg)
PHP 5.3
![Page 16: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/16.jpg)
Namespaces
![Page 17: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/17.jpg)
<?phprequire_once(‘./libs/libA/foo.class.php’);require_once(‘./libs/libB/foo.class.php’);
$foo = new Foo();
Prerequisitos. PHP 5.3 / Namespaces
![Page 18: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/18.jpg)
// ./libs/libA/Foo.php<?phpnamespace LibA;
class Foo {}
// ./libs/libB/Foo.php<?phpnamespace LibB;
class Foo {}
Prerequisitos. PHP 5.3 / Namespaces
![Page 19: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/19.jpg)
// ./index.php<?phpnamespace MyApp;
use LibA\Foo;
$foo = new Foo();
Prerequisitos. PHP 5.3 / Namespaces
![Page 20: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/20.jpg)
// ./index.php<?phpnamespace MyApp;
use LibA\Foo as FooA;use LibB\Foo as FooB;
$fooA = new FooA();$fooB = new FooB();
Prerequisitos. PHP 5.3 / Namespaces
![Page 21: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/21.jpg)
// ./index.php<?phpnamespace MyApp;
$created = new \DateTime();$len = strlen(‘hola’);echo $len . PHP_EOL;
Prerequisitos. PHP 5.3 / Namespaces
![Page 22: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/22.jpg)
Closures
![Page 23: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/23.jpg)
<?php
echo preg_replace_callback('/[a-z]/', function ($match) { return strtoupper($match[0]); }, 'Hola'); // HOLA
Prerequisitos. PHP 5.3 / Closures
![Page 24: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/24.jpg)
Annotations
![Page 25: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/25.jpg)
<?php
/** * @ORM\Column(type="string") * @Assert\NotBlank() */protected $name;
Prerequisitos. PHP 5.3 / Annotations
![Page 26: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/26.jpg)
<?php
/** * @Route("/signup") * @Method({"POST"}) */public function signupAction(){ ...}
Prerequisitos. PHP 5.3 / Annotations
![Page 27: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/27.jpg)
OOP
![Page 28: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/28.jpg)
public $foo;
private $foo;
protected $foo;
Prerequisitos. PHP 5.3 / OOP
![Page 29: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/29.jpg)
<?php
class Foo{ private $a = 1; protected $b = 2; public $c = 3;}
$foo = new Foo();echo $foo->a;
Prerequisitos. PHP 5.3 / OOP
![Page 30: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/30.jpg)
<?php
class Foo{ private $a = 1; protected $b = 2; public $c = 3;}
$foo = new Foo();echo $foo->b;
Prerequisitos. PHP 5.3 / OOP
![Page 31: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/31.jpg)
<?php
class Foo{ private $a = 1; protected $b = 2; public $c = 3;}
class Bar extends Foo { public function getA() { return $this->b; }}
$foo = new Foo();echo $foo->getA();
Prerequisitos. PHP 5.3 / OOP
![Page 32: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/32.jpg)
¿Diferencia entre una interface y una clase abstracta?
Prerequisitos. PHP 5.3 / OOP
![Page 33: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/33.jpg)
Prerequisitos. PHP 5.3 / OOP// JsonInterface.phpinterface JsonInterface{ const MAX_DEPTH = 100;
public function exportJson();}
// User.phpclass User implements{ public function exportJson() { return array( 'username' => $this->username; ); }}
![Page 34: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/34.jpg)
Prerequisitos. PHP 5.3 / OOP
// BaseController.phpabstract class BaseController{ public function getCurrentUser() { ... }}
// UserController.phpclass UserController extends BaseController{ ...}
![Page 35: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/35.jpg)
¿Puede haber herencia entre interfaces?
Prerequisitos. PHP 5.3 / OOP
![Page 36: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/36.jpg)
Prerequisitos. PHP 5.3 / OOP
<?php
namespace DemoBundle\Entity;
class User{ public function setBirthday(\DateTime $date) { $this->birthday = $date; }{
![Page 37: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/37.jpg)
YAML
![Page 38: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/38.jpg)
“YAML is a human friendly data serialization standard for all programming languages. YAML is a great format for your configuration files. YAML
files are as expressive as XML files and as readable as INI files.”
Prerequisitos. YAML
![Page 39: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/39.jpg)
parameters: database_driver: pdo_mysql database_host: localhost database_port: ~ database_name: db_test database_user: db_user_test database_password: db_pass_test
Prerequisitos. YAML
![Page 40: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/40.jpg)
parameters: emails: [ ‘[email protected]’, ‘[email protected]’ ] webs: - ‘web1.com’ - ‘web2.com’ technologies: { PHP: 5.3, MySQL: 5.1 }
Prerequisitos. YAML
![Page 41: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/41.jpg)
MVC
![Page 42: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/42.jpg)
Prerequisitos. MVC
![Page 43: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/43.jpg)
PSR-0 (Autoloading)
![Page 44: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/44.jpg)
<?php
require_once(‘classes/page.php’);require_once(‘classes/chapter.php’);require_once(‘classes/book.php’);
$book = new Book(‘my book’);$chapter = new Chapter(‘chapter 1’);$book->addChapter($chapter);
Prerequisitos. PSR-0 (Autoloading)
![Page 45: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/45.jpg)
<?php
require_once(‘autoload.php’);
$book = new Book(‘my book’);$chapter = new Chapter(‘chapter 1’);$book->addChapter($chapter);
Prerequisitos. PSR-0 (Autoloading)
![Page 46: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/46.jpg)
FQN(Fully Qualified Name) Ruta
\Symfony\Component\Filesystem\Filesystem
[path]/Symfony/Component/Filesystem/Filesystem.php
\Twig_Function [path]/Twig/Function.php
Prerequisitos. PSR-0 (Autoloading)
![Page 47: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/47.jpg)
¿Impacto en el rendimiento de la aplicación?
Prerequisitos. PSR-0 (Autoloading)
![Page 48: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/48.jpg)
PSR-1, PSR-2 (Coding Standards)
![Page 49: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/49.jpg)
<?php
function a($b){ if ($b > 1) { return $b; } return 0;}
function a($b) { if ($b > 1) return $b; return 0;}
Prerequisitos. PSR-1, PSR-2 (Coding Standards)
![Page 50: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/50.jpg)
https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md
https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md
Prerequisitos. PSR-1, PSR-2 (Coding Standards)
![Page 51: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/51.jpg)
Introducción a SF2
![Page 52: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/52.jpg)
Historia
![Page 53: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/53.jpg)
Fabien Potencier
Introducción a Symfony2. Historia
![Page 54: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/54.jpg)
Versión Fecha PHP
1.0 Enero 2007 >= 5.0
1.1 Junio 2008 >= 5.1
1.2 Diciembre 2008 >= 5.2
1.3 Noviembre 2009 >= 5.2.4
1.4 Noviembre 2009 >= 5.2.4
2.0 Julio 2011 >= 5.3.2
2.1 Septiembre 2012 >= 5.3.3
Introducción a Symfony2. Historia
![Page 55: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/55.jpg)
Arquitectura
![Page 56: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/56.jpg)
BrowserKit
ClassLoader
Config
Console
CssSelector
DependencyInjection
DomCrawler
EventDispatcher
Finder
Form
HttpFoundation
Locale
Process
HttpKernel
Routing
Security
Serializer
Templating
Translation
Validator
Yaml
Introducción a Symfony2. Arquitectura
![Page 57: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/57.jpg)
Introducción a Symfony2. Arquitectura
Componentes + Bundles + Librerías externas
Full-stack framework
![Page 58: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/58.jpg)
Distribuciones
![Page 59: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/59.jpg)
Gestión de dependencias con Composer
![Page 60: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/60.jpg)
Introducción a Symfony2. Composer
![Page 61: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/61.jpg)
“Composer is a tool for dependency management in PHP. It allows you to declare
the dependent libraries your project needs and it will install them in your project for you”
Introducción a Symfony2. Composer
![Page 62: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/62.jpg)
$ curl -s https://getcomposer.org/installer | php
$ sudo mv composer.phar /usr/local/bin/composer
Introducción a Symfony2. Composer
![Page 63: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/63.jpg)
Opción Descripción
list Lista de opciones
self-update Actualizar composer
create-project Crea proyecto a partir dependencia
init Crear composer.json básico
validate Valida el archivo composer.json
install Instala dependencias (.lock, .json)
update Actualiza dependencias + .lock
Introducción a Symfony2. Composer
![Page 64: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/64.jpg)
# composer.json
{ "name": "raulfraile/demo_composer", "description": "Demo composer", "require": { "symfony/console": "2.1.*" }}
Introducción a Symfony2. Composer
![Page 65: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/65.jpg)
# composer.json
{ "name": "raulfraile/demo_composer", "description": "Demo composer", "require": { "php": ">=5.3.3", "symfony/console": "2.1.*" }}
Introducción a Symfony2. Composer
![Page 66: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/66.jpg)
# composer.json
{ "name": "raulfraile/demo_composer", "description": "Demo composer", "require": { "php": ">=5.3.3", "symfony/console": "2.1.*", "doctrine/orm": ">=2.2.3,<2.4-dev", }}
Introducción a Symfony2. Composer
![Page 67: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/67.jpg)
Demo: Composer + Console component
![Page 68: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/68.jpg)
• Ejercicio. Crear un proyecto de consola que a partir de unos archivos en YAML con información sobre facturas, proporcione los siguientes comandos:
summary (year): Muestra el total del año introducido (por defecto el actual).
add date total: Añade un nuevo importe al archivo YAML correspondiente.
Utilizar los componentes Console, Yaml y Finder. Para hacer debug os puede ser de utilidad el paquete raulfraile/ladybug.
Introducción a Symfony2. Composer
![Page 69: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/69.jpg)
Inyección de dependencias
![Page 70: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/70.jpg)
"Dependency Injection is where components are given their dependencies through their constructors, methods, or directly
into fields."
Introducción a Symfony2. Inyección de dependencias
![Page 71: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/71.jpg)
class UserController{ private $em;
public function __construct() { $this->em = new EntityManager(); }}
$userController = new UserController();
Introducción a Symfony2. Inyección de dependencias
![Page 72: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/72.jpg)
class UserController{ private $em;
public function __construct() { $this->em = new EntityManager(‘conn2’); }}
$userController = new UserController();
Introducción a Symfony2. Inyección de dependencias
![Page 73: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/73.jpg)
class UserController{ private $em;
public function __construct(EntityManager $em) { $this->em = $em; }}
$em = new EntityManager();$userController = new UserController($em);
Introducción a Symfony2. Inyección de dependencias
![Page 74: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/74.jpg)
DIC: Contenedor de Inyección de Dependencias
![Page 75: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/75.jpg)
use Symfony\Component\DependencyInjection;use Symfony\Component\DependencyInjection\Reference; $sc = new DependencyInjection\ContainerBuilder();$sc->register('mailer', 'MyMailer');$sc->register('em.main', 'MyEntityM') ->setArguments(array('conn1'));$sc->register('logger', 'MyLogger') ->setArguments(array(new Reference('em.main')));
$sc->get('logger');
Introducción a Symfony2. Inyección de dependencias
![Page 76: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/76.jpg)
Entornos de ejecución
![Page 77: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/77.jpg)
Mismo código
Diferentes configuraciones
Introducción a Symfony2. Entornos de ejecución
![Page 78: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/78.jpg)
Entorno ¿Mostrar errores?
Cachear consultas
Base de datos
dev Sí No bd_dev
prod No Sí bd_prod
Introducción a Symfony2. Entornos de ejecución
![Page 79: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/79.jpg)
Instalación y configuración
![Page 80: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/80.jpg)
$ composer create-project symfony/framework-standard-edition path/ 2.1.3
Introducción a Symfony2. Instalación y configuración
![Page 81: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/81.jpg)
Introducción a Symfony2. Instalación y configuración
![Page 82: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/82.jpg)
Documentación
![Page 83: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/83.jpg)
Introducción a Symfony2. Documentación
![Page 84: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/84.jpg)
Primeras páginas
![Page 85: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/85.jpg)
Bundles
![Page 86: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/86.jpg)
Todo el contenido de nuestra aplicaciónestará dentro de uno o más bundles
Primeras páginas. Bundles
![Page 87: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/87.jpg)
Primeras páginas. Bundles
$ php app/console generate:bundle
![Page 88: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/88.jpg)
Primeras páginas. Bundles
// app/AppKernel.php
class AppKernel extends Kernel{ public function registerBundles() { $bundles = array( new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), new Symfony\Bundle\SecurityBundle\SecurityBundle(), new Symfony\Bundle\TwigBundle\TwigBundle(), new Symfony\Bundle\MonologBundle\MonologBundle(), new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(), new Symfony\Bundle\AsseticBundle\AsseticBundle(), new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(), ... );
if (in_array($this->getEnvironment(), array('dev', 'test'))) { $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle(); }
return $bundles; }}
![Page 89: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/89.jpg)
Primeras páginas. Bundles
![Page 90: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/90.jpg)
Routing
![Page 91: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/91.jpg)
Primeras páginas. Routing
/user/profile/raulfraile
Controlador: UserControllerAcción: showProfile($username)
![Page 92: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/92.jpg)
Primeras páginas. Routing
# routing.ymluser_profile: pattern: /user/profile/{username} defaults: { _controller: DemoBundle:User:profile }
![Page 93: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/93.jpg)
Primeras páginas. Routing
# routing.ymlusers_list: pattern: /user/list/{page} defaults: { _controller: DemoBundle:User:list, page: 1 }
![Page 94: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/94.jpg)
Primeras páginas. Routing
# routing.ymlusers_list: pattern: /user/list/{page} defaults: { _controller: DemoBundle:User:list, page: 1 } requirements: page: \d+
![Page 95: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/95.jpg)
Primeras páginas. Routing
# routing.ymlusers_list: pattern: /user/list/{page}{subpage} defaults: { _controller: DemoBundle:User:list, page: 1 } requirements: page: \d+ _method: GET
![Page 96: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/96.jpg)
Primeras páginas. Routing
# user.ymluser_profile: pattern: /profile/{username} defaults: { _controller: DemoBundle:User:profile }
# routing.ymluser_routing: resource: "@DemoBundle/Resources/config/user.yml" prefix: /user
![Page 97: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/97.jpg)
Primeras páginas. Routing
$ php app/console router:debug [route_name]
![Page 98: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/98.jpg)
Primeras páginas. Routing
$ php app/console router:match path
![Page 99: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/99.jpg)
Controladores
![Page 100: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/100.jpg)
Request Response
Primeras páginas. Controladores
![Page 101: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/101.jpg)
use Symfony\Component\HttpFoundation\Response;
class UserController{ public function helloAction() { return new Response('Hello world!'); }}
Primeras páginas. Controladores
![Page 102: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/102.jpg)
use Symfony\Component\HttpFoundation\Response;
class UserController{ public function helloAction($name) { return new Response('Hello '.$name.'!'); }}
Primeras páginas. Controladores
![Page 103: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/103.jpg)
use Symfony\Component\HttpFoundation\Response;use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class UserController extends Controller{ public function helloAction($name) { return new Response('Hello '.$name.'!'); }}
Primeras páginas. Controladores
![Page 104: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/104.jpg)
public function indexAction(){ return $this->redirect($this->generateUrl('home'));}
Primeras páginas. Controladores
![Page 105: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/105.jpg)
public function indexAction(){ throw $this->createNotFoundException('Not found');}
Primeras páginas. Controladores
![Page 106: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/106.jpg)
Demo: Controladores + objeto Request
![Page 107: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/107.jpg)
• Ejercicio. Crear todas las rutas del proyecto, con sus respectivos controladores:
Primeras páginas. Controladores
Ruta Controller
/register AccountController
/book/{slug} BookController
/technology/{slug} TechnologyController
/author/{slug} AuthorController
/book/buy/{slug} BookController
/book/buy_confirm/{slug} BookController
/user/{username} UserController
/account/profile AccountController
/account/password AccountController
/search?q={consulta}&offset={offset}&limit={limit} SearchController
/api/book/latest ApiController
/api/book/featured ApiController
![Page 108: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/108.jpg)
• Ejercicio. En la página de ‘search’, mostrar los valores de los 3 parámetros (query, offset y limit), además de:
• IP del usuario
• Idiomas del usuario (e idioma preferido)
• Nombre de la ruta que está cogiendo
Primeras páginas. Controladores
![Page 109: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/109.jpg)
• Ejercicio. En las páginas de la API generar un JSON con los datos solicitados (de momento de prueba) y devolviendo las cabeceras correctas.
Content-Type: application/json
Primeras páginas. Controladores
![Page 110: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/110.jpg)
• Ejercicio. En la página de ‘technology’, cuando se pidan libros de tecnología ‘java’, se debe redirigir al usuario para mostrar los libros de tecnología ‘php’ y además mostrar un mensaje diciendo ‘PHP es mejor’.
Ayuda: flash messages
• $session->getFlashBag()->add('notice', 'Profile updated');
• $session->getFlashBag()->get('notice', null);
Primeras páginas. Controladores
![Page 111: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/111.jpg)
Twig
![Page 112: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/112.jpg)
Sintaxis básica
![Page 113: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/113.jpg)
{{ }}
{% %}
{# #}
Twig. Sintaxis básica
![Page 114: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/114.jpg)
{{ name }}
Twig. Sintaxis básica - Variables
{{ user.name }}
{{ user[‘name’] }}
![Page 115: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/115.jpg)
{% set foo = 'foo' %}
{% set foo = [1, 2] %}
{% set foo = {'foo': 'bar'} %}
Twig. Sintaxis básica - Variables
![Page 116: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/116.jpg)
{{ name|upper }}
{{ name|striptags|nlbr }}
Twig. Sintaxis básica - Filtros
![Page 117: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/117.jpg)
abscapitalize
convert_encodingdate
date_modifydefaultescapeformat
joinjson_encode
keyslengthlowermerge
nl2brnumber_format
rawreplacereverse
slicesortsplit
striptagstitletrim
upperurl_encode
Twig. Sintaxis básica - Filtros
![Page 118: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/118.jpg)
{{ random(['rojo', 'azul', 'verde']) }}
{{ random('ABC') }}
{{ random() }}
{{ random(5) }}
Twig. Sintaxis básica - Funciones
![Page 119: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/119.jpg)
{{ path('home') }}
<a href=”{{ path(‘user_profile’, {‘username’: user.username }) }}”>
Twig. Sintaxis básica - Funciones
![Page 120: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/120.jpg)
{{ url('home') }}
{{ url(‘user_profile’, {‘username’: user.username }) }}
Twig. Sintaxis básica - Funciones
![Page 121: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/121.jpg)
{% for user in users %} <li>{{ user.username }}</li>{% endfor %}
Twig. Sintaxis básica - Control de flujo
![Page 122: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/122.jpg)
{% for user in users %} <li>{{ user.username }}</li>{% else %} <li>No hay usuarios</li>{% endfor %}
Twig. Sintaxis básica - Control de flujo
![Page 123: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/123.jpg)
{% for user in users %} <li>{{ loop.index }} {{ user.username }}</li>
{% endfor %}
Twig. Sintaxis básica - Control de flujo
![Page 124: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/124.jpg)
{% for user in users if user.active %} <li>{{ user.username }}</li>{% endfor %}
Twig. Sintaxis básica - Control de flujo
![Page 125: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/125.jpg)
{% for key, user in users %} <li>{{ user.username }}</li>{% endfor %}
Twig. Sintaxis básica - Control de flujo
![Page 126: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/126.jpg)
{% if user.active %} <p>Usuario activo</p>{% endif %}
Twig. Sintaxis básica - Control de flujo
![Page 127: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/127.jpg)
{% if user.status == 0 %} <p>Inactivo</p>{% elseif user.status == 1 %} <p>Activo</p>{% else %} <p>Deshabilitado</p>{% endif %}
Twig. Sintaxis básica - Control de flujo
![Page 128: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/128.jpg)
• Ejercicio. Crear la vista search.html.twig, para que muestre exactamente los mismo que antes, pero utilizando Twig.
Ayuda: $this->render(‘DemoBundle::search.html.twig’, array());
Twig. Sintaxis básica
![Page 129: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/129.jpg)
• Ejercicio. En la página del autor, simular que se devuelven libros de la base de datos con un array y crear una tabla/lista con Twig de los títulos de los libros.
Los títulos deberían ser un enlace a la página de cada uno de los libros.
Twig. Sintaxis básica
![Page 130: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/130.jpg)
Herencia
![Page 131: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/131.jpg)
{% include %}
{% extends %}
{% render %}
Twig. Herencia
![Page 132: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/132.jpg)
{# _footer.html.twig #}<footer>© {{ “now”|date(‘Y’) }}</footer>
{# home.html.twig #}<html> <head> <title>Ejemplo include</title> </head> <body> ... {% include ‘_footer.html.twig’ %} </body></html>
Twig. Herencia
![Page 133: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/133.jpg)
{# _footer.html.twig #}<footer>© {{ “now”|date(‘Y’) }}</footer>
{# home.html.twig #}<html> <head> <title>Ejemplo include</title> </head> <body> ... {% include ‘DemoBundle:web:_footer.html.twig’ %} </body></html>
Twig. Herencia
![Page 134: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/134.jpg)
{# layout.html.twig #}<html> <head> <title>{% block title %}{% endblock %}</title> </head> <body> {% block content %}{% endblock %} </body></html>
{# user_profile.html.twig #}{% extends ‘layout.html.twig’ %}{% block title %}Perfil de usuario{% endblock %}{% block content %} <h1>{{ user.username }}</h1>{% endblock %}
Twig. Herencia
![Page 135: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/135.jpg)
{# layout.html.twig #}<html> <head> <title>{% block title %}{% endblock %}</title> </head> <body> {% block content %}{% endblock %} </body></html>
{# user_profile.html.twig #}{% extends ‘DemoBundle::layout.html.twig’ %}{% block title %}Perfil de usuario{% endblock %}{% block content %} <h1>{{ user.username }}</h1>{% endblock %}
Twig. Herencia
![Page 136: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/136.jpg)
{# layout.html.twig #}<html> <head> <title>{% block title %}Título{% endblock %}</title> </head> <body> {% block content %}{% endblock %} </body></html>
{# user_profile.html.twig #}{% extends ‘DemoBundle::layout.html.twig’ %}{% block title %}Perfil de usuario{% endblock %}{% block content %} <h1>{{ user.username }}</h1>{% endblock %}
Twig. Herencia
![Page 137: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/137.jpg)
{# index.html.twig #}<html> <head> <title>Título</title> </head> <body> ... {% render "DemoBundle:Notifications:show" %} </body></html>
Twig. Herencia
![Page 138: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/138.jpg)
• Ejercicio. Crear un layout.html.twig con el código común a todas las páginas y que incluya bloques para: título de la página, css, javascript y contenido.
Utilizar el layout en la página de search.
Twig. Herencia
![Page 139: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/139.jpg)
• Ejercicio. Suponed que queremos tener el código de Google Analytics en todas las páginas, y lo cremos en un archivo _analytics.html.twig, ¿dónde se añadiría?
Además, sólo queremos que salga el código cuando estemos en el entorno de producción. (Ayuda, variable global ‘app’ de Twig).
{{ app|ld }}{{ dump(app) }}
Twig. Herencia
![Page 140: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/140.jpg)
Macros
![Page 141: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/141.jpg)
{# macros.html.twig #}{% macro m_user_box(user) %} <div class=”user_box”> <p>{{ user.username }}</p> </div>{% endmacro %}
{# index.html.twig #}{% import "macros.html.twig" as modules %}
{{ modules.m_user_box(user) }}
Twig. Macros
![Page 142: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/142.jpg)
{# macros.html.twig #}{% macro m_user_box(user) %} <div class=”user_box”> <p>{{ user.username }}</p> </div>{% endmacro %}
{# index.html.twig #}{% import "DemoBundle::macros.html.twig" as modules %}
{{ modules.m_user_box(user) }}
Twig. Macros
![Page 143: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/143.jpg)
• Ejercicio. Crear 2 macros, que nos servirán para mostrar un libro (p.ej. en cualquier listado de libros: search, technologies, author...) y para mostrar un usuario (p.ej. para la lista de usuarios que han comprado ese libro).
Ambas macros deben recibir la información del libro/usuario y enlazar con la página de cada uno de ellos.
Utilizar las 2 macros en las páginas de author y book, simulando que obtenemos los datos de la bd.{# macros.html.twig #}{% macro m_user_box(user) %} <div class=”user_box”> <p>{{ user.username }}</p> </div>{% endmacro %}
{# index.html.twig #}{% import "DemoBundle::macros.html.twig" as modules %}{{ modules.m_user_box(user) }}
Twig. Macros
![Page 144: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/144.jpg)
Extensiones
![Page 145: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/145.jpg)
Oficiales: Twig Extensions Repository
Comunidad
Propias
Twig. Extensiones
![Page 146: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/146.jpg)
Doctrine 2
![Page 147: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/147.jpg)
ORM
![Page 148: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/148.jpg)
ORM: Object Relational Mapper
Doctrine 2. ORM
![Page 149: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/149.jpg)
Doctrine 2. ORM
![Page 150: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/150.jpg)
Doctrine 2. ORM
MySQL
PDO
DBAL
ORM
SQL Server Oracle ...
![Page 151: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/151.jpg)
DBAL
![Page 152: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/152.jpg)
class UserController extends Controller{ public function indexAction() { $conn = $this->get('database_connection'); $users = $conn->fetchAll('SELECT * FROM users'); }}
Doctrine 2. DBAL
![Page 153: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/153.jpg)
Entidades y relaciones
![Page 154: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/154.jpg)
namespace Demo\DemoBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/** * @ORM\Table(name="category") * @ORM\Entity */class Category{ /** * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ protected $id;
/** * @var string $name * @ORM\Column(name="name", type="string", length=255) */ protected $name;}
Doctrine 2. Entidades y relaciones
![Page 155: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/155.jpg)
/** * @ORM\Column(name="twitter", type="string", length=15, nullable=true) */protected $twitter;
/** * @ORM\Column(name="bio", type="text") */protected $bio;
/** * @ORM\Column(name="created_at", type="datetime") */protected $createdAt;
/** * @ORM\Column(name="languages", type="array") */private $languages;
Doctrine 2. Entidades y relaciones
![Page 156: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/156.jpg)
// Relación 1:N unidireccional
// User.php
/** * @var City $city * * @ORM\ManyToOne(targetEntity="City") * @ORM\JoinColumns({ * @ORM\JoinColumn(name="city_id", referencedColumnName="id") * }) */private $city;
Doctrine 2. Entidades y relaciones
![Page 157: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/157.jpg)
// Relación 1:N unidireccional
// User.php
/** * @var City $city * * @ORM\ManyToOne(targetEntity="City") * @ORM\JoinColumns({ * @ORM\JoinColumn(name="city_id", referencedColumnName="id") * }) */private $city;
Doctrine 2. Entidades y relaciones
![Page 158: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/158.jpg)
// Relación 1:N bidireccional
// Post.php
/** * @var User $user * * @ORM\ManyToOne(targetEntity="User", inversedBy="posts") * @ORM\JoinColumns({ * @ORM\JoinColumn(name="user_id", referencedColumnName="id") * }) */protected $user;
// User.php
/** * @var $posts PersistentCollection * * @ORM\OneToMany(targetEntity="Post", mappedBy="user", cascade={"all"}) */protected $posts;
Doctrine 2. Entidades y relaciones
![Page 159: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/159.jpg)
// Relación N:M bidireccional
// Post.php/** * @var $categories PersistentCollection * * @ORM\ManyToMany(targetEntity="Category", inversedBy="posts") * @ORM\JoinTable(name="post_category") */protected $categories;
// Category.php/** * @var $secrets PersistentCollection * * @ORM\ManyToMany(targetEntity="Post", mappedBy="categories") */protected $posts;
Doctrine 2. Entidades y relaciones
![Page 160: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/160.jpg)
Doctrine 2. Entidades y relaciones
$ php app/console doctrine:generate:entity
![Page 161: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/161.jpg)
• Ejercicio. Crear todas las entidades necesarias para la siguiente base de datos:
Doctrine 2. Entidades y relaciones
![Page 162: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/162.jpg)
Configuración
![Page 163: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/163.jpg)
# parameters.yml
parameters: database_driver: pdo_mysql database_host: localhost database_port: ~ database_name: db_name database_user: db_user database_password: db_pass
Doctrine 2. Configuración
![Page 164: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/164.jpg)
Doctrine 2. Configuración
$ php app/console doctrine:schema:update
--dump-sql--force
![Page 165: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/165.jpg)
• Ejercicio. Crear la base de datos del proyecto y el usuario que tendrá acceso. Configurar doctrine y generar el schema definido en las entities.
Recordad que la base de datos debe estar en UTF-8:
CREATE DATABASE books DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
Doctrine 2. Fixtures
![Page 166: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/166.jpg)
Fixtures
![Page 167: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/167.jpg)
{ "require": { "doctrine/doctrine-fixtures-bundle": "dev-master" }}
Doctrine 2. Fixtures
// app/AppKernel.phppublic function registerBundles(){ $bundles = array( // ... new Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle() );}
![Page 168: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/168.jpg)
Doctrine 2. Fixtures
// Demo/DemoBundle/DataFixtures/ORM/LoadUserData.php
namespace Demo\DemoBundle\DataFixtures\ORM;
use Doctrine\Common\DataFixtures\FixtureInterface;use Doctrine\Common\Persistence\ObjectManager;use Demo\DemoBundle\Entity\User;
class LoadUserData implements FixtureInterface{ public function load(ObjectManager $manager) { $user = new User(); $user->setUsername('raulfraile');
$manager->persist($user); $manager->flush(); }}
![Page 169: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/169.jpg)
Doctrine 2. Fixtures// Demo/DemoBundle/DataFixtures/ORM/LoadUserData.php
namespace Demo\DemoBundle\DataFixtures\ORM;
use Doctrine\Common\DataFixtures\AbstractFixture;use Doctrine\Common\DataFixtures\OrderedFixtureInterface;use Doctrine\Common\Persistence\ObjectManager;use Demo\DemoBundle\Entity\User;
class LoadUserData extends AbstractFixture implements OrderedFixtureInterface{ public function getOrder() { return 1; }
public function load(ObjectManager $manager) { // ... $this->addReference('user_' . $user->getUsername(), $user); }}
![Page 170: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/170.jpg)
Doctrine 2. Fixtures// Demo/DemoBundle/DataFixtures/ORM/LoadBookData.php
namespace Demo\DemoBundle\DataFixtures\ORM;
use Doctrine\Common\DataFixtures\AbstractFixture;use Doctrine\Common\DataFixtures\OrderedFixtureInterface;use Doctrine\Common\Persistence\ObjectManager;use Demo\DemoBundle\Entity\Book;
class LoadBookData extends AbstractFixture implements OrderedFixtureInterface{ public function getOrder() { return 2; }
public function load(ObjectManager $manager) { // ... $book->setUser($this->getReference('user_'.$data[‘slug’])); }}
![Page 171: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/171.jpg)
Doctrine 2. Fixtures
$ php app/console doctrine:fixtures:load
--purge-with-truncate
![Page 172: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/172.jpg)
Buenas prácticas
![Page 173: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/173.jpg)
users.yml
books.yml
authors.yml
technologies.yml
Doctrine 2. Fixtures
LoadUserData.php
LoadBookData.php
LoadAuthorData.php
LoadTechnologyData.php
CONST FIXTURE_REF = ‘user’
CONST FIXTURE_REF = ‘books’
CONST FIXTURE_REF = ‘author’
CONST FIXTURE_REF = ‘technology’
![Page 174: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/174.jpg)
• Ejercicio. Crear datos de prueba (incluidas imágenes) en archivos yml, además de los correspondientes scripts para cargar los fixtures.
Doctrine 2. Fixtures
![Page 175: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/175.jpg)
nelmio/alice
![Page 176: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/176.jpg)
• Ejercicio. Rehacer los fixtures para utilizar nelmio/alice y además generar usuarios de prueba utilizando fzaninotto/faker.
Doctrine 2. Fixtures
![Page 177: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/177.jpg)
Repositorios
![Page 178: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/178.jpg)
Doctrine 2. Repositorios
// Demo/DemoBundle/Entity/User.php
/** * @ORM\Entity(repositoryClass="Demo\DemoBundle\Entity\UserRepository") */class User{ //...}
![Page 179: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/179.jpg)
Doctrine 2. Repositorios
// Demo/DemoBundle/Entity/UserRepository.php
use Doctrine\ORM\EntityRepository;
class UserRepository extends EntityRepository{ public function findAllActive() { return $this->getEntityManager() ->createQuery('SELECT u FROM DemoBundle:User u WHERE u.active = TRUE') ->getResult(); }}
![Page 180: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/180.jpg)
Doctrine 2. Repositorios
// Demo/DemoBundle/Entity/UserRepository.php
use Doctrine\ORM\EntityRepository;
class UserRepository extends EntityRepository{ public function findAllFromCountry($country) { return $this->getEntityManager() ->createQuery('SELECT u FROM DemoBundle:User u WHERE u.country = :country') ->setParameter('country', $country); ->getResult(); }}
![Page 181: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/181.jpg)
Doctrine 2. Repositorios
// Demo/DemoBundle/Entity/UserRepository.php use Doctrine\ORM\EntityRepository; class UserRepository extends EntityRepository{ public function findAllFromSpain($limit = null, $offset = null) { $query = $this->getEntityManager() ->createQuery('SELECT u FROM DemoBundle:User u WHERE u.country = :country') ->setParameter('country', 'es'); if (!is_null($limit)) { $query->setMaxResults($limit); } if (!is_null($limit)) { $query->setFirstResult($offset); } return $query->getResult(); }}
![Page 182: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/182.jpg)
Doctrine 2. Repositorios// Demo/DemoBundle/Entity/UserRepository.php
use Doctrine\ORM\EntityRepository;
class UserRepository extends EntityRepository{
public function countUsersFromSpain() { $dql = 'SELECT COUNT(u.id) FROM DemoBundle:User u WHERE u.country = :country'; $query = $this->getEntityManager()->createQuery($dql) ->setParameter('country', 'es') ; try { return $query->getSingleScalarResult(); } catch (\Doctrine\ORM\NoResultException $e) { return 0; }
}}
![Page 183: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/183.jpg)
Doctrine 2. Repositorios// Demo/DemoBundle/Entity/UserRepository.php use Doctrine\ORM\EntityRepository; class UserRepository extends EntityRepository{ public function findAllFromSpain() { $qb = $this->getEntityManager()->createQueryBuilder() ->select('u') ->from('DemoBundle:User', 'u') ->where('u.country = :country') ->orderBy('u.id', 'desc') ; $query = $qb->getQuery(); $query->setParameter('country', 'es'); try { return $query->getResult(); } catch (\Doctrine\ORM\NoResultException $e) { return false; } }}
![Page 184: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/184.jpg)
Doctrine 2. Repositorios
// Demo/DemoBundle/Controller/UserController.php
class UserController extends Controller{ public function listActiveAction() { $em = $this->getEntityManager();
$userRepository = $em->getRepository('DemoBundle:User');
$all = $userRepository->findAll(); $userId1 = $userRepository->find(1); $userRaul = $userRepository->findOneByUsername('raul'); $usersValencia = $userRepository->findOneBy(array( 'active' => true, 'city' => 'Valencia' )); $usersActive = $userRepository->findAllActive(); // custom query }}
![Page 185: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/185.jpg)
• Ejercicio. Una vez tenemos datos de prueba y sabemos como acceder a los datos, crear las siguientes páginas:
- Listado de autores- Perfil público de un usuario
Doctrine 2. Repositorios
![Page 186: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/186.jpg)
Frontend
![Page 187: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/187.jpg)
Gestión de assets
![Page 188: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/188.jpg)
{{ asset('/bundles/books/images/logo.png') }}
Frontend. Gestión de assets
![Page 189: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/189.jpg)
Frontend. Gestión de assets
framework: ... templating: engines: ['twig'] assets_version: v0.2
![Page 190: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/190.jpg)
Frontend. Gestión de assets
http://ejemplo.com/bundles/books/images/logo.png?v0.2
![Page 191: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/191.jpg)
• Ejercicio. Añadir en el layout (utilizando la función ‘asset’ de Twig):
- Logo de la web- Dos archivos CSS con algunos estilos básicos
Una vez añadidos, utilizar la opción para versionar assets y comprobar como la URL cambia en cada cambio de versión.
Frontend. Gestión de assets
php app/console assets:install web/
![Page 192: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/192.jpg)
Assetic
![Page 193: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/193.jpg)
Frontend. Assetic
“Assetic is an asset management framework for PHP, based on the Python webassets library.”
![Page 194: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/194.jpg)
Frontend. Assetic
reset.css
bootstrap.css
global.css
Assets Filtros
styles.css
![Page 195: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/195.jpg)
Frontend. Assetic
CoffeeScriptFilterCssEmbedFilterCssImportFilterCssMinFilterCssRewriteFilterGoogleClosure\CompilerApiFilterGoogleClosure\CompilerJarFilterHandlebarsFilterJpegoptimFilterJpegtranFilterLessFilter
LessphpFilterOptiPngFilterPackerFilterPngoutFilterCompassFilterSass\SassFilterSass\ScssFilterSprocketsFilterStylusFilterYui\CssCompressorFilterYui\JsCompressorFilter
![Page 196: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/196.jpg)
Frontend. Assetic
{% javascripts '@BooksBundle/Resources/public/js/*'%} <script type="text/javascript" src="{{ asset_url }}"> </script>{% endjavascripts %}
![Page 197: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/197.jpg)
Frontend. Assetic
{% javascripts '@BooksBundle/Resources/public/js/1.js' '@BooksBundle/Resources/public/js/2.js' '@BooksBundle/Resources/public/js/3.js'%} <script type="text/javascript" src="{{ asset_url }}"> </script>{% endjavascripts %}
![Page 198: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/198.jpg)
Frontend. Assetic
{% javascripts '@BooksBundle/Resources/public/js/1.js' '@BooksBundle/Resources/public/js/2.js' '@BooksBundle/Resources/public/js/3.js' filter='yui_js' output='js/script.js'%} <script type="text/javascript" src="{{ asset_url }}"> </script>{% endjavascripts %}
![Page 199: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/199.jpg)
Frontend. Assetic
{% javascripts '@BooksBundle/Resources/public/js/1.js' '@BooksBundle/Resources/public/js/2.js' '@BooksBundle/Resources/public/js/3.js' filter='?yui_js' output='js/script.js'%} <script type="text/javascript" src="{{ asset_url }}"> </script>{% endjavascripts %}
![Page 200: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/200.jpg)
Frontend. Assetic
$ php app/console assetic:dump --env=prod
--watch
![Page 201: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/201.jpg)
• Ejercicio. Utilizando Assetic, combinar por separado los 2 css y los 2 javascripts, y comprimiéndolos con YUI Compressor.
Nota: ver entrada del cookbock para detalles de configuración:
http://symfony.com/doc/current/cookbook/assetic/yuicompressor.html
Frontend. Assetic
![Page 202: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/202.jpg)
Tratamiento de imágenes
![Page 203: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/203.jpg)
Frontend. Tratamiento de imágenes
AvalancheImagineBundle
Imagine
GD2
Imagick
Gmagick
![Page 204: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/204.jpg)
Frontend. Tratamiento de imágenes
// GD resize
$width = 80$height = 80$src = imagecreatefrompng('image.png');$dest = imagecreatetruecolor($width, $height);imagealphablending($dest, false);imagesavealpha($dest, true);imagecopyresampled($dest, $src, 0, 0, 0, 0, $width, $height, imagesx($src), imagesy($src));imagepng($dest,'image_resized.png');
![Page 205: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/205.jpg)
Frontend. Tratamiento de imágenes
// Imagick resize
$width = 80;$height = 80;$image = new Imagick('image.png');$image->adaptiveResizeImage($width, $height);$image->writeImage('image_resized.png');
![Page 206: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/206.jpg)
Frontend. Tratamiento de imágenes
// Imagine resize
$width = 80;$height = 80;
$imagine = new Imagine\Gd\Imagine();$imagine = new Imagine\Imagick\Imagine();
$imagine->open('image.png') ->resize(new Imagine\Box($width, $height)) ->save('image_resized.png');
![Page 207: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/207.jpg)
Frontend. Tratamiento de imágenes
http://www.slideshare.net/avalanche123/introduction-toimagine
![Page 208: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/208.jpg)
Frontend. Tratamiento de imágenes
¿Cómo usarlo en Symfony para hacer thumbnails de imágenes subidas por los usuarios?
![Page 209: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/209.jpg)
Frontend. Tratamiento de imágenes
# app/config.yml
avalanche_imagine: filters: user_small: type: thumbnail options: { size: [30, 30], mode: outbound } user_medium: type: thumbnail options: { size: [60, 60], mode: outbound } user_big: type: thumbnail options: { size: [90, 90], mode: outbound }
![Page 210: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/210.jpg)
Frontend. Tratamiento de imágenes
<img src="{{ user.webPath|apply_filter('user_small') }}" />
![Page 211: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/211.jpg)
Demo: AvalancheImagineBundle + Upload Doctrine
![Page 212: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/212.jpg)
Formatos alternativos
![Page 213: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/213.jpg)
Frontend. Formatos alternativos
# routing.yml
api_books_latest: pattern: /api/latest.{_format} defaults: { _controller: BooksBundle:Api:latest }
![Page 214: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/214.jpg)
Frontend. Formatos alternativos
# routing.yml
api_books_latest: pattern: /api/latest.{_format} defaults: { _controller: BooksBundle:Api:latest, _format: html }
![Page 215: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/215.jpg)
Frontend. Formatos alternativos
public function latestAction(){ $format = $this->getRequest()->getRequestFormat();}
![Page 216: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/216.jpg)
• Ejercicio. Generar la API /api/books/latest para que permitan obtener el contenido en JSON y XML, dependiendo del formato pasado. Por ejemplo:
/api/books/latest.xml: contenido en XML
Por defecto, el formato será JSON.
Nota: Algunos formatos son más propensos a ser generados a través de Twig que otros, tenedlo en cuenta.
Frontend. Formatos alternativos
![Page 217: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/217.jpg)
Backend
![Page 218: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/218.jpg)
Formularios
![Page 219: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/219.jpg)
Backend. Formulariosnamespace Books\BooksBundle\Form;
use Symfony\Component\Form\AbstractType;use Symfony\Component\Form\FormBuilderInterface;use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class UserType extends AbstractType{ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('username', 'text'); }
public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'Books\BooksBundle\Entity\User' )); }
public function getName() { return 'form_user'; }}
![Page 220: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/220.jpg)
Backend. Formularios
public function createAction(Request $request){ $user = new User(); $form = $this->createForm(new UserType(), $user); $form->bind($request);
if ($form->isValid()) { $em = $this->getEntityManager(); $em->persist($entity); $em->flush();
return $this->redirect($this->generateUrl('user_created')); }
return $this->render('BooksBundle:Users:new.html.twig', array( 'entity' => $user, 'form' => $form->createView(), ));}
![Page 221: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/221.jpg)
Backend. Formularios
<form action="{{ path('user_create') }}" method="post" {{ form_enctype(form) }}>
{{ form_errors(form) }}
{{ form_row(form) }}
{{ form_rest(form) }}
<input type="submit" /></form>
![Page 222: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/222.jpg)
Backend. Formularios
<form action="{{ path('user_create') }}" method="post" {{ form_enctype(form) }}>
{{ form_errors(form) }}
{{ form_row(form.username) }}
{{ form_rest(form) }}
<input type="submit" /></form>
![Page 223: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/223.jpg)
Backend. Formularios
namespace Books\BooksBundle\Form;
use Symfony\Component\Form\AbstractType;use Symfony\Component\Form\FormBuilderInterface;use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class UserType extends AbstractType{ public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('username', 'text', array( 'required' => true, 'label' => 'Nombre de usuario' 'attr' => array( 'class' => 'text_big' ) ));
$builder->add('email', 'email'); }
...}
![Page 224: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/224.jpg)
Backend. Formularios
text textarea email
integer money number
password percent search
url choice entity
country language locale
timezone date datetime
time birthday checkbox
file radio collection
repeated hidden csrf
field form
![Page 225: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/225.jpg)
Backend. Formularios
http://symfony.com/doc/current/reference/forms/types.html
![Page 226: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/226.jpg)
• Ejercicio. Generar tres nuevas rutas, que servirán para dar de alta un libro desde el backend:
/admin/books/new/admin/books/create/admin/books/created
Crear el formulario para poder introducir nuevos libros en la base de datos. Los campos deberán ser: título (text), descripción (textarea), isbn (text), price (money) y techonology (entity).
Backend. Formularios
![Page 227: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/227.jpg)
• Ejercicio. Realizar el mismo proceso para editar un libro desde el backend, utilizando el mismo formulario.
/admin/books/edit/{id}/admin/books/update/{id}/admin/books/updated
Backend. Formularios
![Page 228: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/228.jpg)
• Ejercicio. Crear el listado de libros con enlaces para editarlos, y un link para añadir un nuevo libro en la parte superior:
/admin/books/list
Backend. Formularios
![Page 229: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/229.jpg)
Backend. Formularios
Generación de CRUDs automáticos
Create Read Update Delete
![Page 230: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/230.jpg)
Backend. Formularios
![Page 231: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/231.jpg)
Backend. Formularios
$ php app/console generate:doctrine:crud
![Page 232: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/232.jpg)
• Ejercicio. Utilizando el generador de CRUD, crear las acciones necesarias para gestionar los libros, a partir de la ruta /admin/v2/books.
Una vez que lo tengamos en funcionamiento, estudiar las acciones que ha creado y añadir lo que considereis necesario en las plantillas, namespaces, formulario... Finalmente, sustituir el CRUD que habíamos hecho a mano por éste, para que se muestre en /admin/books.
Backend. Formularios
![Page 233: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/233.jpg)
Validación
![Page 234: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/234.jpg)
Backend. Validación
/** * @var string $title * * @Assert\NotBlank * @Assert\MaxLength(250) * @ORM\Column(name="title", type="string", length=250) */protected $title;
![Page 235: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/235.jpg)
Backend. Validación
public function createAction(Request $request){ $user = new User(); $form = $this->createForm(new UserType(), $user); $form->bind($request);
if ($form->isValid()) { $em = $this->getEntityManager(); $em->persist($entity); $em->flush();
return $this->redirect($this->generateUrl('user_created')); }
return $this->render('BooksBundle:Users:new.html.twig', array( 'entity' => $user, 'form' => $form->createView(), ));}
![Page 236: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/236.jpg)
Backend. Validación
<form action="{{ path('user_create') }}" method="post" {{ form_enctype(form) }}>
{{ form_errors(form) }}
{{ form_row(form.username) }}
{{ form_rest(form) }}
<input type="submit" /></form>
![Page 237: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/237.jpg)
Backend. Validación
NotBlank Blank NotNullNull TRUE FALSEType Email MinLength
MaxLength Length UrlRegex Ip MaxMin Range Date
DateTime Time ChoiceCollection Count UniqueEntityLanguage Locale Country
File Image CallbackAll UserPassword Valid
Constraints
![Page 238: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/238.jpg)
Backend. Validación
http://symfony.com/doc/current/reference/constraints.html
![Page 239: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/239.jpg)
• Ejercicio. Añadir las siguientes reglas de validación al modelo de datos:
Author: - country: código de país válido - name: valor requerido
Book: - isbn: isbn válido de 10 dígitos - price: no puede ser negativo
User: - email: email válido - locale: locale válido - username: letras, números o caracter “_”, de una longitud mínima de 3 y máxima de 15
Backend. Validación
![Page 240: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/240.jpg)
Seguridad
![Page 241: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/241.jpg)
Autenticación VS Autorización
![Page 242: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/242.jpg)
Seguridad. Autenticación VS Autorización
Firewall Control de acceso
![Page 243: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/243.jpg)
Seguridad. Autenticación VS Autorización
![Page 244: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/244.jpg)
Seguridad. Autenticación VS Autorización
![Page 245: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/245.jpg)
Seguridad. Autenticación VS Autorización
![Page 246: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/246.jpg)
Seguridad. Autenticación VS Autorización
![Page 247: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/247.jpg)
Roles
![Page 248: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/248.jpg)
Seguridad. Roles
Usuario
ROLE_USER
ROLE_ADMIN
ROLE_TRANSLATOR
![Page 249: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/249.jpg)
Seguridad. Roles
Usuario
ROLE_USER
ROLE_ADMIN
ROLE_TRANSLATOR
![Page 250: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/250.jpg)
Configuración
![Page 251: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/251.jpg)
Seguridad. Configuraciónsecurity: encoders: Symfony\Component\Security\Core\User\User: plaintext
role_hierarchy: ROLE_ADMIN: ROLE_USER ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers: in_memory: memory: users: user: { password: userpass, roles: [ 'ROLE_USER' ] } admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] }
firewalls: dev: pattern: ^/(_(profiler|wdt)|css|images|js)/ security: false
login: pattern: ^/demo/secured/login$ security: false
secured_area: pattern: ^/demo/secured/ form_login: check_path: /demo/secured/login_check login_path: /demo/secured/login logout: path: /demo/secured/logout target: /demo/ #anonymous: ~
access_control: #- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https } #- { path: ^/_internal/secure, roles: IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 }
![Page 252: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/252.jpg)
Seguridad. Configuración
security: encoders: Empresa\BooksBundle\Entity\User: sha512 role_hierarchy: ROLE_ADMIN: ROLE_USER ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH] providers: main: entity: { class: Empresa\BooksBundle\Entity\User, property: username } firewalls: dev: pattern: ^/(_(profiler|wdt)|css|images|js)/ security: false main: pattern: ^/ form_login: check_path: /login_check login_path: /login logout: path: /logout target: / anonymous: true access_control: - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/admin/, role: ROLE_ADMIN }
Symfony\Component\Security\Core\User\UserInterface
getRoles()getPassword()
getSalt()getUsername()
eraseCredentials()
![Page 253: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/253.jpg)
Login
![Page 254: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/254.jpg)
Seguridad. Login
# app/config/routing.ymllogin: pattern: /login defaults: { _controller: EmpresaBooksBundle:Security:login }
login_check: pattern: /login_checklogout: pattern: /logout
![Page 255: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/255.jpg)
Seguridad. Login
// src/Empresa/BooksBundle/Controller/SecurityController.php;namespace Empresa\BooksBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller;use Symfony\Component\Security\Core\SecurityContext; class SecurityController extends Controller{ public function loginAction() { $request = $this->getRequest(); $session = $request->getSession(); // get the login error if there is one if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) { $error = $request->attributes->get( SecurityContext::AUTHENTICATION_ERROR ); } else { $error = $session->get(SecurityContext::AUTHENTICATION_ERROR); $session->remove(SecurityContext::AUTHENTICATION_ERROR); } return $this->render( 'EmpresaBooksBundle:Security:login.html.twig', array( // last username entered by the user 'last_username' => $session->get(SecurityContext::LAST_USERNAME), 'error' => $error, ) ); }}
![Page 256: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/256.jpg)
Seguridad. Login
{# src/Empresa/BooksBundle/Resources/views/Security/login.html.twig #}{% if error %} <div>{{ error.message }}</div>{% endif %} <form action="{{ path('login_check') }}" method="post"> <label for="username">Username:</label> <input type="text" id="username" name="_username" value="{{ last_username }}" /> <label for="password">Password:</label> <input type="password" id="password" name="_password" /> <button type="submit">login</button></form>
![Page 257: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/257.jpg)
Servicios y eventos
![Page 258: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/258.jpg)
Servicios
![Page 259: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/259.jpg)
Demo: Servicios
![Page 260: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/260.jpg)
Eventos
![Page 261: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/261.jpg)
Demo: Eventos
![Page 262: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/262.jpg)
Extendiendo SF2
![Page 263: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/263.jpg)
Comandos personalizados
![Page 264: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/264.jpg)
Extendiendo Symfony2. Comandos personalizados
// src/Empresa/BooksBundle/Command/BooksListCommand.php
class BooksListCommand extends ContainerAwareCommand{ protected function configure() { $this ->setName('books:list') ->setDescription('Books list') ; }
protected function execute(InputInterface $input, OutputInterface $output) { $em = $this->getContainer()->get('doctrine.orm.entity_manager');
$books = $em->getRepository('BooksBundle:Book')->findAll();
foreach ($books as $book) { $output->writeln($book->getTitle()); } }}
![Page 265: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/265.jpg)
• Ejercicio. Crear el comando books:author, que muestre por consola los libros de un determinado autor, introducido por parámetro:
php app/console books:author author_id
Backend. Validación
![Page 266: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/266.jpg)
Extensiones de Twig
![Page 267: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/267.jpg)
Extendiendo Symfony2. Extensiones de Twig
// src/Empresa/BooksBundle/Twig/HtmlExtension.php
class HtmlExtension extends \Twig_Extension{
public function getFunctions() { return array( 'strong' => new \Twig_Function_Method($this, 'getStrong', array('is_safe' => array('html'))) ); }
public function getStrong($text) { return '<strong>' . $text . '</strong>'; }
public function getName() { return 'html'; }}
![Page 268: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/268.jpg)
Extendiendo Symfony2. Extensiones de Twig
# services.yml
books.twig.html_extension: class: Empresa\BooksBundle\Twig\HtmlExtension tags: - { name: twig.extension }
![Page 269: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/269.jpg)
• Ejercicio. Crear una función de Twig que reciba un objeto de tipo libro y devuelva una cadena de texto con el título del libro y el nombre del autor entre paréntesis.
Backend. Validación
![Page 270: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/270.jpg)
Rendimiento
![Page 271: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/271.jpg)
![Page 272: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/272.jpg)
![Page 273: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/273.jpg)
Optimización y rendimiento
Ejecutar controlador frontal (app[_dev].php)
Procesar archivos de configuración
Cargar bundles
Cargar rutas y decidir la ruta solicitada
Ejecutar controlador interno
Parsear plantilla Twig
Generar respuesta (contenido + headers)
![Page 274: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/274.jpg)
Optimización y rendimiento
Cache
![Page 275: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/275.jpg)
Optimización y rendimiento
![Page 276: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/276.jpg)
APC
![Page 277: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/277.jpg)
Optimización y rendimiento. APC
Byte Code Cache
![Page 278: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/278.jpg)
Optimización y rendimiento. APC
Lee el archivo index.php y lo introduce en memoria
GET /index.php HTTP/1.1
El analizador léxico (lexer) lee el código fuente y genera una serie de “tokens”
El analizador sintáctico (parser) parsea los tokens y genera una serie de “opcodes”, los cuales son ejecutados
directamente por el motor de PHP
Se ejecutan los “opcodes”
![Page 279: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/279.jpg)
Optimización y rendimiento. APC
La primera vez se realizan los mismos pasos (lexer + parser) para generar los “opcodes”. Una vez generados
se guardan en memoria.
GET /index.php HTTP/1.1 (con APC)
Las siguientes veces utiliza los “opcodes” guardados en memoria y los ejecuta directamente
![Page 280: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/280.jpg)
Optimización y rendimiento. APC
System/User cache
![Page 281: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/281.jpg)
Optimización y rendimiento. APC
// app.php
$loader = require_once __DIR__.'/../app/bootstrap.php.cache';
$loader = new ApcClassLoader('books', $loader);$loader->register(true);
![Page 282: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/282.jpg)
Optimización y rendimiento. APC
# app/config/config_prod.yml
doctrine: orm: metadata_cache_driver: apc result_cache_driver: apc query_cache_driver: apc
![Page 283: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/283.jpg)
Composer
![Page 284: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/284.jpg)
Optimización y rendimiento. Composer
$ composer dump-autoload --optimize
![Page 285: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/285.jpg)
Extra
![Page 286: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/286.jpg)
Seguridad
![Page 287: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/287.jpg)
• Ejercicio. Configurar la seguridad de Symfony2 para utilizar la entity User como proveedor de usuarios, codificando los passwords con sha512 y definiendo roles. Crear la página de login, y cuando el usuario esté logueado mostrar su nombre y un enlace para hacer logout.
Extra. Seguridad
![Page 288: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/288.jpg)
• Ejercicio. Crear la página /myprofile, que mostrará los datos del usuario actual, y solo se podrá acceder si está logueado y tiene el rol ROLE_USER.
Extra. Seguridad
![Page 289: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/289.jpg)
• Ejercicio. Crear la página /myadmin, a la que solo se podrá acceder si el usuario logueado tiene el rol ROLE_ADMIN.
Extra. Seguridad
![Page 290: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/290.jpg)
Doctrine 2. Repositorios
![Page 291: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/291.jpg)
• Ejercicio. Crear la página /search, que recibirá dos parámetros por GET: type y query:
/search?type=book&query=programming
Dependiendo de ‘type’ hará una búsqueda fulltext de libros (por título, descripción e isbn), autores (por nombre), tecnologías (por nombre) o usuarios (por username).
Extra. Doctrine2 Repositorios
![Page 292: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/292.jpg)
• Ejercicio. Crear la página /sales, que mostrará los 5 libros más baratos.
Extra. Doctrine2 Repositorios
![Page 293: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/293.jpg)
• Ejercicio. Añadir un campo llamado ‘active’ a las entidades ‘Book’ y ‘Author’, de tipo boolean. Cambiar los fixtures para tener libros/autores activos e inactivos. Crear la página /stats que muestre:
- Número de libros activos- Número de libros inactivos- Número de autores activos- Número de autores inactivos- Media de autores por libro
Extra. Doctrine2 Repositorios
![Page 294: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/294.jpg)
Formularios
![Page 295: Materiales del curso de Symfony2](https://reader031.fdocumento.com/reader031/viewer/2022013118/54881e86b4af9f640d8b556a/html5/thumbnails/295.jpg)
• Ejercicio. Añadir tres campos a la entity User:
- birthday- country- bio
Crear la página /myprofile/edit para editar los datos del perfil del usuario actual y /myprofile/password para cambiar el password (solicitando el password actual y pidiéndolo por duplicado).
Crear el método hasLegalAgeForDrink() en la entity User, que devolverá TRUE si el usuario es mayor de edad, dependiendo del país: (es: 18, us: 21, ir: ilegal)
http://en.wikipedia.org/wiki/Legal_drinking_age
Extra. Formularios