Symfony2, tutorial para comenzar ultra-rápido

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”?

27 mar 2011

25 Respuestas a “Symfony2, tutorial para comenzar ultra-rápido”

  1. 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. 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. RT @miquelcamps: Symfony2, tutorial para comenzar ultra-rápido http://bit.ly/f434up

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

  5. montes dice:

    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. RT @miquelcamps: Symfony2, tutorial para comenzar ultra-rápido http://bit.ly/f434up

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

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

    Un saludo!

  9. yyeshua dice:

    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. RT @miquelcamps: Symfony2, tutorial para comenzar ultra-rápido http://bit.ly/f434up

  11. enel dice:

    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. frieser dice:

    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

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

  14. Denis dice:

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

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

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

  17. Interesante :-) RT @kunfu_code: #Symfony2 , tutorial para comenzar ultra-rápido http://t.co/JpQjD7dG

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

  19. @AleNoSeVale quizás te interese esto “@kunfu_code: #Symfony2 , tutorial para comenzar ultra-rápido http://t.co/WZZ55AC4”

  20. José Luis Ramirez dice:

    Buenos días a todos, sou nuevo en symfony 2 y no tengo ninguna experiencia en programación web, pero deseo aprender bien del tema, algo que no he visto en los tutoriales y quisiera si ustedes pueden ayudar en eso, es hacer un tutorial desde cero, de cómo programar con netbeans y symfony2. Incluso desde la instalación y configuración del entorno netbeans tanto para windows como para linux fedora. Muchas gracias por su respuesta, espero por ustedes.

  21. @Marydn dice:

    ¡Lee, lee! =P RT @hvallenilla Symfony2, Tutorial http://t.co/gwkNax6l

Deja un comentario