Symfony es El Framework PHP. Y como todo Framework, se basa en una serie de reglas y buenas prácticas definidas para trabajar con él.

Durante los más de 5 años que en XandruSoft llevamos desarrollando proyectos con Symfony, hemos recopilado la mayoría de las funciones, configuraciones, comandos y código que se utilizan en el día a día de cualquier proyecto, y queremos compartirlos con vosotros.

 

Gitignore

Link de referencia https://github.com/github/gitignore/blob/master/Symfony.gitignore

Contenido para nuestro .gitignore

# Symfony project .gitignore file with the recomendation github for MAVEN project structure
# Updated by Xandrusoft.com
# System files
.DS_Store
.classpath

[membership level=»0″][/membership][membership level=»1,2″]

.project
.settings
.buildpath
.idea/ 

# Cache and logs (Symfony2)
/app/cache/*
/app/logs/*
!app/cache/.gitkeep
!app/logs/.gitkeep

# Email spool folder
/app/spool/*

# Cache, session files and logs (Symfony3)
/var/cache/*
/var/logs/*
/var/sessions/*
!var/cache/.gitkeep
!var/logs/.gitkeep
!var/sessions/.gitkeep

# Parameters
/app/config/parameters.yml
/app/config/parameters.ini

# Managed by Composer
/app/bootstrap.php.cache
/var/bootstrap.php.cache
!app/console
!app/symfony_requirements
/vendor/

# Assets and user uploads
/web/bundles/
/web/uploads/

# Assets managed by Bower
/web/assets/vendor/

# PHPUnit
/app/phpunit.xml
/phpunit.xml

# Bin
/bin/

# Build data
/build/

# Composer PHAR
/composer.phar
/composer.lock

# Backup entities generated with doctrine:generate:entities command
*/Entity/*~

[/membership]

Routing

Comprobar las rutas existentes

$ php app/console debug:router | grep api

Reglas

Routing general

backend:
  resource: "@BackendBundle/Resources/config/routing.yml"
  prefix:   /back
  host:     backend.myproject.com
  schemes:  [https]

Routing Bundle yml

backend_task_view:
  path:     /task/{task}
  defaults: { _controller: BackendBundle:Task:view }
  requirements:
     task: \d+
  methods: [GET]

Routing Bundle annotation

/**
* @Route("/", name="homepage", defaults={"id" = 1}, requirements={"id" = "\d+"})
* @Method({"GET", "POST"})
*/
public function indexAction(Request $request)
Controllers

Generar un nuevo controlador

$ php app/console generate:controller –no-interaction –controller=BackendBundle:Rooms

Responses

Respuestas proporcionadas por el controlador (debemos recordar que Symfony es un Framework HTTP Request/Response)

json

$response = new JsonResponse();
$response->setData(array(
));
return $response;
Entities

Crear base de datos

$ php app/console doctrine:database:create

Crear entidad

$ php app/console generate:doctrine:entity –format=annotation –entity=BackendBundle:Products

Generar datos

$ php app/console doctrine:generate:entities BackendBundle:Products –no-backup

Actualizar db

$ php app/console doctrine:schema:update –dump-sql

$ php app/console doctrine:schema:update –force

Ingeniería reversa (reverse engineering)

$ php app/console doctrine:mapping:import –force BackendBundle php

Entity Manager controller

$em = $this->getDoctrine()->getManager();
$room_repo = $em->getRepository('BackendBundle:Products');
$rooms = $room_repo->findIndexProperties('4','es');

Consultas

FindOneBy -> Devuelve un objeto

FindBy -> Devuelve un array de objetos

Se relacionan los datos

/**
* @ORM\ManyToOne(targetEntity="Application\Sonata\MediaBundle\Entity\Media", inversedBy="expense", cascade={"persist"})
* @ORM\JoinColumn(name="media_id", referencedColumnName="id")
*/
protected $media;

No se relacionan los datos

/**
* @ORM\OneToMany(targetEntity="Expense", mappedBy="media", cascade={"persist"})
*/
protected $expense;

/**
* Constructor
*/
public function __construct()
{
   $this->expense = new \Doctrine\Common\Collections\ArrayCollection();
}

ToString

Esta función se utiliza para definir el string que devolverá cuando se haga referencia a la entidad directamente.  Entre otros se utiliza en los formularios, vistas, Sonata Admin, etc.

[membership level=»0″][/membership][membership level=»1,2″]

public function __toString()
  {
      $return = $this->feature;
      if ($return == »)
          $return = ‘-‘;
      return (string)$return;
  }
[/membership]

Const

Las constantes se utilizan en las entidades para definir los distintos valores (estáticos) que puede tener un campo. Un ejemplo común puede ser el estado de un artículo de un blog (publicado, borrador, borrado). Definir estas constantes para un campo nos permitirá obtener sus valores desde los formularios, vistas, etc. sin necesidad de volver a definir sus valores

class ContactResource
{
   const TYPE_PHONE = 1;
   const TYPE_EMAIL = 2;

[membership level=»0″][/membership][membership level=»1,2″]

   public static $resourceType = array(
       ContactResource::TYPE_PHONE => "Phone",
       ContactResource::TYPE_EMAIL => "Email"
   );

/**
* @var integer
*
* @ORM\Column(type="integer", length=2)
*
*/
private $type;

public function __toString()
{
   return (string)$this->getType();
}

public function getType()
{
   if (!is_null($this->type)) {
       return self::$resourceType[$this->type];
   } else {
       return null;
   }
}

public static function getTypeList() {
   return self::$resourceType;
}
}

Sonata Admin

->add('type', 'choice', array(
       'help' => "Type of resource",
       'choices' => ContactResource::getTypeList()
   )
)

Compare

$entity->getType() == ContactResource::TYPE_SKYPE

Twig

entity.type == constant(TYPE_SKYPE, entity)

{% if var == constant('ContactResource::TYPE_SKYPE') %} 
{# or #} 
{% if var is constant('ContactResource::TYPE_SKYPE') %}

Form

$builder->andWhere('type = :type') ->setParameter('type', ContactResource::TYPE_SKYPE)

[/membership]

Validaciones

[membership level=»0″][/membership][membership level=»1,2″]

use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;

/**
* Ecommerce
*
* @ORM\Table(name="services__ecommerce")
* @ORM\Entity(repositoryClass="SmartDataProtection\IndexBundle\Repository\EcommerceRepository")
* @UniqueEntity("identifier")
* @Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=false)
* @ExclusionPolicy("all")
*/
class Ecommerce implements EcommerceInterface

/**
* @var string
*
* @Assert\Length(
*      min = "1",
*      max = "255",
* )
* @Assert\NotBlank()
* @Assert\NotNull()
*
* @ORM\Column(name="identifier", type="string", length=255, unique=true)
*/
private $identifier;

[/membership]

DateTime

/**
* @var \DateTime
*
* @ORM\Column(name="date", type="datetime", nullable=true)
*/
private $date;

Boolean

/**
* @var boolean
*
* @ORM\Column(name="complete", type="boolean", nullable=true)
*/
private $complete;

Prepersist / Preupdate

[membership level=»0″][/membership][membership level=»1,2″]

/**
* Project
*
* @ORM\Table(name="products")
* @ORM\Entity()
* @ORM\HasLifecycleCallbacks()
*/

/**
* @ORM\PrePersist
* @ORM\PreUpdate
*/
public function calculateRevenues()
{

[/membership]

Default values in constructor

/**
* Constructor
*/
public function __construct()
{
   $this->device = new \Doctrine\Common\Collections\ArrayCollection();
   $this->dateReg = new \DateTime();
}

DQL

DQL es el lenguaje que Doctrine nos proporciona para trabajar con las bases de datos dentro de nuestros proyecto Symfony. La ventaja de utilizar DQL frente a consultas SQL u otro lenguaje es que permite abstraerse de la tecnología utilizada como base de datos, siendo el propio Doctrine quien traduce al lenguaje correspondiente estas consultas. Con ello, podremos desplegar nuestro proyecto en cualquier servidor de base de datos.

[membership level=»0″][/membership][membership level=»1,2″]

$datetime = new \DateTime('now');
$datetime->modify('+1 day');
$from = new \DateTime($datetime->format("Y-m-d")." 00:00:00");
$to   = new \DateTime($datetime->format("Y-m-d")." 23:59:59");

$qb = $this->createQueryBuilder("t");
$qb
    ->andWhere('t.user = :user')
    ->andWhere('t.date BETWEEN :from AND :to')
    ->andWhere('t.complete != TRUE')
    ->setParameter('from', $from )
    ->setParameter('to', $to)
    ->setParameter('user', $user)
    ->orderBy('t.date','DESC')
;
$result = $qb->getQuery()->getResult();
return $result;

-------

$q = $this->getEntityManager()->createQueryBuilder();
$q->select('ds.name')
   ->from('\BackBundle\Entity\Features','p')
   ->join('\BackBundle\Entity\FeaturesLangs', 'ds', 'WITH', 'p = ds.feature')
   ->join('\BackBundle\Entity\Languages', 'ln', 'WITH', 'ds.language = ln')
   ->where('p.id = :feature')
   ->andWhere('ln.iso = :lang')
   ->setParameter('lang', $locale)
   ->setParameter('feature', $feature)
   ->setMaxResults(1)
;
$query = $q->getQuery();
$result = $query->getOneOrNullResult();

[/membership]

Random unique id

$this->identifier = bin2hex(openssl_random_pseudo_bytes(25));

Canonicals

[membership level=»0″][/membership][membership level=»1,2″]

use Gedmo\Mapping\Annotation as Gedmo;

/**
* @var string
*
* @Gedmo\Slug(fields={«name»}, updatable=true, separator=«-«)
* @ORM\Column(name=«canonical_name», type=«string», length=255, unique=true)
*/
private $canonicalName;
[/membership]