Symfony2, tutorial para comenzar ultra-rápido

Posted: March 27th, 2011 | Author: | Filed under: programacion | Tags: | 17 Comments »

This post in english at http://en.mooontes.com/2011/03/27/symfony2-ultra-fast-start-tutorial/

NOTA: Este tutorial se ha realizado en Ubuntu 11.04 – Natty Narwhal, no se ha comprobado su funcionamiento en otros sistemas operativos. Esto es sólo una especie de chuleta de ejemplo por si se te olvida alguna cosa tras leer la documentación de symfony2, pero evidentemente es imprescindible leérsela antes para saber de qué va todo esto :) http://symfony.com/doc/2.0/book/index.html

El código fuente utilizado está disponible en: https://github.com/montes/Adictos-Symfony2-Bundle

ACTUALIZACIÓN 23/5/2011: Actualizado para symfony2 beta2

 

1. Descarga

Descarga Symfony2 Standard Edition (en el momento de escribir esto la BETA2): http://symfony.com/download

Descomprime

tar -zxvf Symfony_Standard_Vendors_2.0.0BETA2.tgz

Y cambia los permisos de app/cache y app/logs para que sean escribibles por php, por ejemplo:

chmod 777 app/cache app/logs

Configura en tu servidor el directorio “web/” como raíz y ya deberías poder cargar la página de bienvenida de symfony2 desde http://127.0.0.1/app_dev.php/

 

2. Configura la base de datos

Configura app/config/parameters.ini con las opciones de tu base de datos (también lo puedes hacer desde http://127.0.0.1/app_dev.php/_configurator/ ), para mysql sería algo así:

[parameters]
    database_driver=pdo_mysql
    database_host=localhost
    database_name=symfony2
    database_user=symfony2
    database_password=password
    mailer_transport=smtp
    mailer_host=localhost
    mailer_user=
    mailer_password=
    locale=en
    csrf_secret=op234j234j2424jojpfwesdcsdc

 

3. Crear nuestro primer bundle

Ahora ya podemos crear un bundle:

php app/console init:bundle "Montes\AdictosBundle" src

Ahora toca añadir a app/autoload.php :

$loader->registerNamespaces(array(
    'Montes'                         => __DIR__.'/../src',
    // ...
));

y añadir a app/AppKernel.php :

    $bundles = array(
        // ...
        new Montes\AdictosBundle\MontesAdictosBundle(),
    );

 

4. Ruta

Para que symfony2 sepa dónde enviar las peticiones, añadimos a app/config/routing_dev.yml :

homepage:
    pattern:  /adictos
    defaults: { _controller: MontesAdictosBundle:Default:index }

En este punto ya podemos cargar nuestro recién creado bundle yendo a: http://127.0.0.1/app_dev.php/adictos

 

5. Controller

El controller por defecto (Montes/AdictosBundle/Controller/DefaultController.php) ya nos lo ha creado Symfony2, ahora vamos a crear el controller StoreController.php

//Montes/AdictosBundle/Controller/StoreController.php
<?php

namespace Montes\AdictosBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

class StoreController extends Controller
{
    /**
     * @Template()
     */
    public function indexAction($store)
    {
        return array('store' => $store);
    }
}

y añadimos a app/config/routing_dev.yml

store:
    pattern: /adictos/{store}
    defaults: { _controller: MontesAdictosBundle:Store:index }

y una nueva plantilla de twig a Montes/AdictosBundle/Resources/Views/Store/index.html.twig

So you want store "{{ store }}"?

Y ahora cargando http://127.0.0.1/app_dev.php/adictos/mi-tienda obtendremos:

So you want store “mi-tienda”?

 

6. Modelo

NOTA: Para entrar en detalle sobre Doctrine2 recomiendo el blog de Francisco Belmonte, una maravilla.

Primero añadimos a app/config/config.ymlMontesAdictosBundle: ~ A partir de la BETA1 por defecto el mapping es automático.

Comenzamos con Doctrine, vamos a definir nuestro modelo para una tienda. Antes de nada, como aún no hemos creado ningún modelo tendremos que crear el directorio Montes/AdictosBundle/Entity que es donde los guardaremos todos.

Y ya podemos empezar, modelo para Store:

<?php
// Montes/AdictosBundle/Entity/Store.php

namespace Montes\AdictosBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 */
class Store
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
     protected $id;

    /**
     * @ORM\ManyToMany(targetEntity="Category")
     * @ORM\JoinTable(name="stores_categories",
     *      joinColumns={@ORM\JoinColumn(name="store_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="category_id", referencedColumnName="id")})
     */
    protected $categories;

    /**
     * @ORM\Column(type="string", length="255")
     */
    protected $url;

    /**
     * @ORM\Column(type="string", length="255")
     */
    protected $name;

    /**
     * @ORM\Column(type="integer")
     */
    protected $clicks = 0;

    /**
     * @ORM\Column(type="boolean")
     */
    protected $validated = false;

    /**
     * @ORM\Column(type="integer")
     */
    protected $pcomments = 0;

    /**
     * @ORM\Column(type="integer")
     */
    protected $ncomments = 0;

    /**
     * @ORM\Column(type="boolean")
     */
    protected $active = false;

    /**
     * @ORM\Column(type="datetime", name="updated_at")
     */
    protected $updatedAt;

    /**
     * @ORM\Column(type="datetime", name="created_at")
     */
    protected $createdAt;

    public function __construct()
    {
        $this->categories = new \Doctrine\Common\Collections\ArrayCollection();
        $this->createdAt = new \DateTime();
        $this->updatedAt = new \DateTime();
    }
}

Modelo para Category:

<?php
// Montes/AdictosBundle/Entity/Category.php

namespace Montes\AdictosBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 */
class Category
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\OneToMany(targetEntity="Category", mappedBy="parent")
     */
    protected $children;

    /**
     * @ORM\ManyToOne(targetEntity="Category", inversedBy="children")
     * @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
     * @ORM\Column(nullable="true")
     */
    protected $parent;

    /**
     * @ORM\ManyToMany(targetEntity="Store", mappedBy="categories")
     */
    protected $stores;

    /**
     * @ORM\Column(type="string", length="255")
     */
    protected $name;

    /**
     * @ORM\Column(type="string", length="255", name="url_string", unique="true")
     */
    protected $urlString;

    public function __construct()
    {
        $this->stores = new \Doctrine\Commmon\Collections\ArrayCollection();
    }
}

Y ahora vamos a consola y para generar las tablas en la base de datos ejecutamos:

php app/console doctrine:schema:create

y para completar nuestro modelo con sus getters/setters:

php app/console doctrine:generate:entities MontesAdictosBundle

 

7. Probando el modelo

Vamos a cambiar la acción que muestra la tienda a su propia acción (storeAction) para hacer hueco al índice del store controller en indexAction, que ahora mostrará el total de tiendas que tenemos almacenadas en la BD.

# app/config/routing_dev.yml
store:
    pattern: /adictos/{store}
    defaults: { _controller: MontesAdictosBundle:Store:store }

store_index:
    pattern: /adictos/
    defaults: { _controller: MontesAdictosBundle:Store:index }
<?php
// Montes/AdictosBundle/Controller/StoreController.php

namespace Montes\AdictosBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

class StoreController extends Controller
{

    /**
     * @Template()
     */
    public function indexAction()
    {
        $em = $this->get('doctrine.orm.entity_manager');
        $stores = $em->createQuery('SELECT count(s.id) AS total FROM Montes\AdictosBundle\Entity\Store s')->getSingleScalarResult();
        return array('stores' => $stores);
    }

    /**
     * @Template()
     */
    public function storeAction($store)
    {
        return array('store' => $store);
    }
}
<!-- Montes/AdictosBundle/Resources/views/Store/index.html.twig -->
We have a total of {{ stores }} stores.
<!-- Montes/AdictosBundle/Resources/views/Store/store.html.twig -->
So you want store "{{ store }}"?

Ahora al cargar http://127.0.0.1/app_dev.php/adictos/ nos saldrá We have a total of 0 stores y al cargar http://127.0.0.1/app_dev.php/adictos/mi-tienda nos saldrá So you want store “mi-tienda”?
Fork me on GitHub


17 Comments on “Symfony2, tutorial para comenzar ultra-rápido”

  1. 1 php,debian,mysql... (@mooontes) said at 02:14 on March 27th, 2011:

    ya me puedo ir a la cama, primer post sobre #symfony2 listo, a ver si mañana pongo el segundo… zzzzZZZzz http://bit.ly/fWrX1R

  2. 2 Albert Jessurum said at 13:55 on March 28th, 2011:

    Dos cositas a corregir.
    Revisar que en los routings, algunos salen :default { controller: … y deben ser todos: _controller (sin el guion bajo no carga)

    La otra, que estas usando annotations en los controladores, pero Symfony no los esta usando para las rutas, solo esta usando las que declaras por yml.
    Para usar las anotaciones que tienes en los controladores hay que importarlos en app/config/routing.yml asi:

    montes:
    resource: “@MontesAdictosBundle/Controller/StoreController.php”
    type: annotation

    (y usar una forma o la otra, no hacen falta los dos formas).

    Igual, excelente la inicativa, y muy clara la guia!

  3. 3 Albert Jessurum (@ajessu) said at 14:09 on March 28th, 2011:

    RT @miquelcamps: Symfony2, tutorial para comenzar ultra-rápido http://bit.ly/f434up

  4. 4 Daniel Casasnovas (@pardalsalcap) said at 14:51 on March 28th, 2011:

    RT @miquelcamps: Symfony2, tutorial para comenzar ultra-rápido http://bit.ly/f434up

  5. 5 montes said at 17:31 on March 28th, 2011:

    Hola Albert, los “_controller” están bien pero algunos parece que les falta el guión bajo por el css que lo tapa.

    Toda la razón con el routing, muchísimas gracias, creo que ya está corregido ;)

  6. 6 colorate (@colorate) said at 20:10 on March 28th, 2011:

    RT @miquelcamps: Symfony2, tutorial para comenzar ultra-rápido http://bit.ly/f434up

  7. 7 Pedro Teruel Giménez (@pedrotgimenez) said at 20:31 on March 28th, 2011:

    RT @AsierMarques: RT @jonseg: RT @miquelcamps Symfony2, tutorial para comenzar ultra-rápido http://bit.ly/f434up

  8. 8 Albert Jessurum said at 09:02 on March 29th, 2011:

    Ya vi lo de los controladores y el css, gracias por la aclaracion :) , no me habia fijado que estaban escondidas.

    Un saludo!

  9. 9 yyeshua said at 16:34 on March 29th, 2011:

    Oh, buenísimo. Esto me hubiese ahorrado algunas horas hace un par de días cuando llegué casi al mismo proceso leyendo la documentación y a ensayo y error XD. Pero me viene muy bien de recordatorio para seguir practicando.

    En todo caso, a ver si os interesa hacer un tutorial ultra rápido para poner a funcionar el UserBundle que todavía no consigo hacerlo. XD

    Saludos.

  10. 10 Dan El Chalbzouri (@bonzzaydan) said at 18:37 on March 29th, 2011:

    RT @miquelcamps: Symfony2, tutorial para comenzar ultra-rápido http://bit.ly/f434up

  11. 11 enel said at 14:59 on May 17th, 2011:

    hola me ayudas un poco mas con symfony estoy empezando con symfony 2 soy estudiante de informatica me gustaria aprender esta nueva version quien me ayuda

  12. 12 Pedro Teruel Giménez (@pedrotgimenez) (@pedrotgimenez) said at 22:06 on May 23rd, 2011:

    Tutorial para comenzar a usar #symfony2: http://bit.ly/lJqU7C

  13. 13 frieser said at 19:39 on May 25th, 2011:

    Hola, excelente post!

    Me da la siguiente excepcion al terminar de crear el controlador:

    The autoloader expected class “Montes\AdictosBundle\Controller\StoreController” to be defined in file “/home/xxxxx/proyecto/app/../src/Montes/AdictosBundle/Controller/StoreController.php”. You probably have a typo in the namespace or the class name.

    Parece que falla al cargar la clase en el autoloader, pero no veo como solucionarlo. ¿Alguien tiene alguna idea?
    Gracias

  14. 14 Oscar Miguel Amezcua (@Obelich) said at 21:46 on June 10th, 2011:

    Aca les dejo el manual que estoy usando para entenderle a #Symfony2 http://goo.gl/Vqfea

  15. 15 Denis said at 19:40 on July 25th, 2011:

    Simplemente Excelente!!…que bueno que existan personas como vos que brindan recursos a la comunidad Symfony. Gracias

  16. 16 Roberto Santana (@robertosanval) said at 06:52 on October 1st, 2011:

    Chuleta para #symfony2 http://t.co/UG74yP7R

  17. 17 Javier A. Alvarez (@neiker) said at 00:13 on January 27th, 2012:

    Symfony2, tutorial para comenzar ultra-rápido http://t.co/t213Q2xp


Leave a Reply