SlideShare a Scribd company logo
1 of 89
Frameworks de desarrollo

Symfony
Clase 4

                       Javier Eguíluz
                       javier.eguiluz@gmail.com
Esta obra dispone de una licencia de tipo Creative
Commons Reconocimiento‐No comercial‐ Compartir 
             bajo la misma licencia 3.0 




 Se prohíbe explícitamente el uso de este material en 
        actividades de formación comerciales

http://creativecommons.org/licenses/by‐nc‐sa/3.0/es/
This work is licensed under a Creative Commons
  Attribution‐Noncommercial‐Share Alike 3.0 




    The use of these slides in commercial courses or
            trainings is explicitly prohibited

 http://creativecommons.org/licenses/by‐nc‐sa/3.0/es/
Capítulo 16

Servicios web
long tail
sitio1.com




sitio2.com




sitio3.com




sitio4.com
Los afiliados
data/fixtures/030_affiliates.yml
JobeetAffiliate:
  sensio_labs:
    url:       http://www.sensio‐labs.com/
    email:     fabien.potencier@example.com
    is_active: true
    token:     sensio_labs
   jobeet_category_affiliates: [programming]

 symfony:
   url:       http://www.symfony‐project.org/
   email:     fabien.potencier@example.org
   is_active: false
   token:     symfony
   jobeet_category_affiliates: [design, programming]
lib/model/JobeetAffiliate.php

class JobeetAffiliate extends BaseJobeetAffiliate
{
  public function save(PropelPDO $con = null)
  {
    if (!$this‐>getToken())
    {
      $this‐>setToken(
        sha1($this‐>getEmail().rand(11111, 99999))
      );
    }

        return parent::save($con);
    }

    // ...
}
apps/frontend/config/routing.yml
api_jobs:
  url:   /api/:token/jobs.:sf_format
  class: sfPropelRoute
  param: { module: api, action: list }
  options: { model: JobeetJob, type: list, method: getForToken }
  requirements:
    sf_format: (?:xml|json|yaml)


                                    lib/model/JobeetJobPeer.php
static public function getForToken(array $parameters) {
    $affiliate = JobeetAffiliatePeer::getByToken($parameters['token']);
    if (!$affiliate || !$affiliate‐>getIsActive()) {
      throw new sfError404Exception('...');
    }
    return $affiliate‐>getActiveJobs();
}
lib/model/JobeetAffiliate.php
class JobeetAffiliate extends BaseJobeetAffiliate
{
  public function getActiveJobs()
  {
    $cas = $this‐>getJobeetCategoryAffiliates();
    $categories = array();
    foreach ($cas as $ca) {
      $categories[] = $ca‐>getCategoryId(); 
    }
    $criteria = new Criteria();
    $criteria‐>add(
      JobeetJobPeer::CATEGORY_ID,
      $categories,
      Criteria::IN
    ); 
    JobeetJobPeer::addActiveJobsCriteria($criteria);
    return JobeetJobPeer::doSelect($criteria);
  }
}
$ ./symfony generate:module frontend api


         apps/frontend/modules/api/actions/actions.class.php

public function executeList(sfWebRequest $request)
{
  $this‐>jobs = array();
  foreach ($this‐>getRoute()‐>getObjects() as $job)
  {
    $url = $this‐>generateUrl('job_show_user', $job, true);
    $this‐>jobs[$url] = $job‐>asArray($request‐>getHost());
  }
}
XML




petición                   JSON


           executeList()
                           YAML
apps/frontend/modules/api/templates/listSuccess.xml.php

<?xml version=quot;1.0quot; encoding=quot;utf‐8quot;?>
<jobs>
<?php foreach ($jobs as $url => $job): ?>
  <job url=quot;<?php echo $url ?>quot;>
<?php foreach ($job as $key => $value): ?>
  <<?php echo $key ?>>
    <?php echo $value ?>
  </<?php echo $key ?>>
<?php endforeach; ?>
  </job>
<?php endforeach; ?>
</jobs>
apps/frontend/modules/api/templates/listSuccess.json.php
[
<?php
$nb = count($jobs); $i = 0;
foreach ($jobs as $url => $job): ++$i ?>
{
  quot;urlquot;: quot;<?php echo $url ?>quot;,
<?php
  $nb1 = count($job); $j = 0;
  foreach ($job as $key => $value): ++$j ?>
  quot;<?php echo $key ?>quot;: <?php echo json_encode($value).
                                    ($nb1 == $j ? '' : ',') ?>
<?php endforeach; ?>
}<?php echo $nb == $i ? '' : ',' ?>

<?php endforeach; ?>
]
Cómo crear un nuevo formato

 1. Crear la plantilla de la acción 
   (xxxSuccess.formato.php)
 2. Deshabilitar el layout y establecer el Content‐
   Type de la respuesta
 3. Crear las páginas de error y de excepción
   (config/error/[error|exception].formato.yml)
apps/frontend/modules/api/templates/listSuccess.yaml.php

<?php foreach ($jobs as $url => $job): ?>
‐
  url: <?php echo $url ?>

<?php foreach ($job as $key => $value): ?>
  <?php echo $key ?>: <?php echo sfYaml::dump($value) ?>

<?php endforeach; ?>
<?php endforeach; ?>




$this‐>setLayout(false);
$this‐>getResponse()‐>setContentType('text/yaml');
config/error/exception.yaml.php
<?php echo sfYaml::dump(array(
  'error' => array(
    'code' => $code,
    'message' => $message,
    'debug' => array(
      'name' => $name,
      'message' => $message,
      'traces' => $traces,
    ),
)), 4) ?>

                         config/error/error.yaml.php
<?php echo sfYaml::dump(array(
  'error' => array(
    'code' => $code,
    'message' => $message,
))) ?> 
apps/frontend/templates/layout.yaml.php




<?php echo $sf_content ?> 
El formulario para 
darse de alta como 
      afiliado
apps/frontend/config/routing.yml
 affiliate:
   class: sfPropelRouteCollection
   options:
     model:          JobeetAffiliate
     actions:        [new, create]
     object_actions: { wait: get }




$ ./symfony propel:generate‐module frontend affiliate
JobeetAffiliate ‐‐non‐verbose‐templates
apps/frontend/modules/affiliate/templates/newSuccess.php
<?php use_stylesheet('job.css') ?>
<h1>Conviértete en afiliado</h1>
<?php include_partial('form', array('form' => $form)) ?> 



        apps/frontend/modules/affiliate/templates/_form.php
<?php include_stylesheets_for_form($form) ?>
<?php include_javascripts_for_form($form) ?>
<?php echo form_tag_for($form, 'affiliate') ?>
...
<input type=quot;submitquot; value=quot;Submitquot; />
...
<?php echo $form ?>
</form>
apps/frontend/modules/affiliate/templates/waitSuccess.php

<h1>Your affiliate account has been created</h1>
<div style=quot;padding: 20pxquot;>
  ¡Gracias! Pronto recibirás un email... 
</div>



                       apps/frontend/templates/layout.php
...
<li class=quot;lastquot;>
  <a href=quot;<?php echo url_for('@affiliate_new') ?>quot;>
    Become an affiliate
  </a>
</li>
...
Administrando los 
   afiliados
$ ./symfony propel:generate‐admin backend
JobeetAffiliate ‐‐module=affiliate
apps/backend/modules/affiliate/config/generator.yml
  config:
    fields:
      is_active: { label: Active? }
    list:
      title:   Affiliate Management
      display: [is_active, url, email, token]
      sort:    [is_active]
      object_actions:
        activate:   ~
        deactivate: ~
      batch_actions:
        activate:   ~
        deactivate: ~
      actions: {}
    filter:
      display: [url, email, is_active]


apps/backend/modules/affiliate/lib/affiliateGeneratorConfiguration.class.php
  public function getFilterDefaults() {
    return array('is_active' => '0');
  }
Enviando emails
Zend Framework


                   Zend_Mail
quot;Zend_Mail provides generalized functionality to compose
and send both text and MIME‐compliant multipart e‐mail 
messages. Mail can be sent with Zend_Mail via the default
    Zend_Mail_Transport_Sendmail transport or via
             Zend_Mail_Transport_Smtpquot;
1. Descargar Zend Framework

     Descomprimirlo en lib/vendor/Zend
2.

     Eliminar todo salvo:
3.

           Loader/              Exception.php
       •                    •
           Loader.php           Mime/
       •                    •
           Mail/                Mime.php
       •                    •
           Mail.php             Search/
       •                    •
config/ProjectConfiguration.class.php
class ProjectConfiguration extends sfProjectConfiguration {
  static protected $zendLoaded = false;

    static public function registerZend() {
      if (self::$zendLoaded) {
        return;
      }

        set_include_path(sfConfig::get('sf_lib_dir').
                         '/vendor'.
                         PATH_SEPARATOR.
                         get_include_path()
        );

        require_once sfConfig::get('sf_lib_dir').
                     '/vendor/Zend/Loader.php';

        Zend_Loader::registerAutoload();
        self::$zendLoaded = true;
    }
}
apps/backend/modules/affiliate/actions/actions.class.php


ProjectConfiguration::registerZend();
$mail = new Zend_Mail();

$mail‐>setBodyText(quot;Hemos activado tu cuenta y tu 
token secreto es {$affiliate‐>getToken()}quot;)
  ‐>setFrom('jobeet@example.com', 'Jobeet Bot')
  ‐>addTo($affiliate‐>getEmail())
  ‐>setSubject('Jobeet affiliate token')
  ‐>send();
Capítulo 17

El buscador
La tecnología
quot;No reinventes la ruedaquot;

      NIH (Not Invented Here)
 “persistent sociological, corporate or institutional
culture that avoids using or buying already existing
  products, research or knowledge because of its
                  different origins”
Zend Framework


           Zend_Search_Lucene
quot;...un buscador genérico de texto escrito completamente 
   con PHP 5. Como guarda sus índices en archivos y no 
requiere de un servidor de bases de datos, permite incluir 
 un buscador en cualquier sitio web construido con PHP.quot;
1. Descargar Zend Framework

     Descomprimirlo en lib/vendor/Zend
2.

     Eliminar todo salvo:
3.

           Loader/              Exception.php
       •                    •
           Loader.php           Mime/
       •                    •
           Mail/                Mime.php
       •                    •
           Mail.php             Search/
       •                    •
config/ProjectConfiguration.class.php
class ProjectConfiguration extends sfProjectConfiguration {
  static protected $zendLoaded = false;

    static public function registerZend() {
      if (self::$zendLoaded) {
        return;
      }

        set_include_path(sfConfig::get('sf_lib_dir').
                         '/vendor'.
                         PATH_SEPARATOR.
                         get_include_path()
        );

        require_once sfConfig::get('sf_lib_dir').
                     '/vendor/Zend/Loader.php';

        Zend_Loader::registerAutoload();
        self::$zendLoaded = true;
    }
}
Índices
lib/model/JobeetJobPeer.php

static public function getLuceneIndex() {
  ProjectConfiguration::registerZend();

    if (file_exists($index = self::getLuceneIndexFile())) {
      return Zend_Search_Lucene::open($index);
    } else {
      return Zend_Search_Lucene::create($index);
    }
}

static public function getLuceneIndexFile() {
  return sfConfig::get('sf_data_dir').
         '/job.'.
         sfConfig::get('sf_environment').
         '.index';
}
lib/model/JobeetJob.php

public function save(PropelPDO $con = null)
{
  // ...

    $ret = parent::save($con);

    $this‐>updateLuceneIndex();

    return $ret;
}
lib/model/JobeetJob.php
public function updateLuceneIndex() {
  $index = JobeetJobPeer::getLuceneIndex();

    $doc = new Zend_Search_Lucene_Document();

    $doc‐>addField(Zend_Search_Lucene_Field::UnIndexed(
       'pk',
       $this‐>getId())
    );

    $doc‐>addField(Zend_Search_Lucene_Field::UnStored(
       'position',
       $this‐>getPosition(), 'utf‐8')
    );
    // ...

    $index‐>addDocument($doc);
    $index‐>commit();
}
lib/model/JobeetJob.php
public function save(PropelPDO $con = null) {
  // ...
  if (is_null($con)) {
        $con = Propel::getConnection(JobeetJobPeer::DATABASE_NAME, Propel::CONNECTION_WRITE);
    }

    $con‐>beginTransaction();
    try {
      $ret = parent::save($con);
      $this‐>updateLuceneIndex();
      $con‐>commit();
      return $ret;
    }
    catch (Exception $e) {
      $con‐>rollBack();
      throw $e;
    }
}
lib/model/JobeetJob.php



public function delete(PropelPDO $con = null)
{
  $index = JobeetJobPeer::getLuceneIndex();
  if ($hit = $index‐>find('pk:'.$this‐>getId()))
  {
    $index‐>delete($hit‐>id);
  }

    return parent::delete($con);
}
Búsquedas
apps/frontend/config/routing.yml
job_search:
  url:   /search
  param: { module: job, action: search }

               apps/frontend/modules/job/actions/actions.class.php
class jobActions extends sfActions
{
  public function executeSearch(sfWebRequest $request) {
    if (!$query = $request‐>getParameter('query')) {
      return $this‐>forward('job', 'index');
    }
    $this‐>jobs = JobeetJobPeer::getForLuceneQuery($query); 
  }
  // ...
}
lib/model/JobeetJobPeer.php

static public function getForLuceneQuery($query) {
  $hits = self::getLuceneIndex()‐>find($query);

    $pks = array();
    foreach ($hits as $hit) {
      $pks[] = $hit‐>pk;
    }

    $criteria = new Criteria();
    $criteria‐>add(self::ID, $pks, Criteria::IN);
    $criteria‐>setLimit(20);

    return self::doSelect(self::addActiveJobsCriteria($criteria));
}
Capítulo 18

AJAX
web/js/jquery‐1.2.6.min.js
Incluyendo jQuery
apps/frontend/templates/layout.php

  ...
  <?php use_javascript('jquery‐1.2.6.min.js') ?>
  <?php include_javascripts() ?>
</head>

                    mejora el 
                    rendimiento

  ...
  <?php include_javascripts() ?>
</body>
Añadiendo los 
comportamientos
$('#search_keywords').keyup(function(key)
{
  if (this.value.length >= 3 || this.value == '')
  {
    $('#jobs').load(
       $(this).parents('form').attr('action'),
       { query: this.value + '*' }
    );
  }
});

$('.search input[type=quot;submitquot;]').hide();
web/js/search.js
$(document).ready(function()
{
  $('.search input[type=quot;submitquot;]').hide();
  $('#search_keywords').keyup(function(key)
  {
    if (this.value.length >= 3 || this.value == '')
    {
      $('#loader').show();
      $('#jobs').load(
        $(this).parents('form').attr('action'),
        { query: this.value + '*' },
        function() { $('#loader').hide(); }
      );
    }
  });
});
                      apps/frontend/templates/layout.php
<?php use_javascript('search.js') ?>
AJAX en las acciones
AJAX                JavaScript


                  layout +
layout +
                  searchSuccess.php
renderPartial()
apps/frontend/modules/job/actions/actions.class.php

public function executeSearch(sfWebRequest $request)
{
  if (!$query = $request‐>getParameter('query'))
  {
    return $this‐>forward('job', 'index');
  }

    $this‐>jobs = JobeetJobPeer::getForLuceneQuery($query);

    if ($request‐>isXmlHttpRequest())
    {
                                        AJAX
      return $this‐>renderPartial(
        'job/list',
        array('jobs' => $this‐>jobs)
      );
    }
}
apps/frontend/modules/job/actions/actions.class.php
public function executeSearch(sfWebRequest $request)
{
  if (!$query = $request‐>getParameter('query'))
  {
    return $this‐>forward('job', 'index');
  }

    $this‐>jobs = JobeetJobPeer::getForLuceneQuery($query);

    if ($request‐>isXmlHttpRequest())
    {
      if ('*' == $query || !$this‐>jobs) {
        return $this‐>renderText('No results.');
      }
      else {
        return $this‐>renderPartial(
          'job/list',
          array('jobs' => $this‐>jobs)
        );
      }
    }
}
http://www.symfony‐project.org/api/1_2/sfAction




    renderText()
    renderPartial()
    renderComponent()
Capítulo 19

i18n y l10n
i18n y l10n
quot;La internacionalización es el proceso de diseñar aplicaciones de 
software que puedan ser adaptadas a distintos idiomas y 
regiones sin necesidad de realizar cambios en su ingeniería.quot;


quot;La localización es el proceso de adaptar el software para una 
región o idioma específicos mediante la inclusión de componentes 
específicos de esa región y mediante la traducción del texto.quot;
El usuario
idioma + país = cultura
    es_ES        fr_FR
    es_AR        fr_BE
    es_MX        fr_CA
    es_PE
idioma (ISO 3166‐1)

                  país (ISO 639‐1)

$this‐>getUser()‐>setCulture('fr_BE');

echo $this‐>getUser()‐>getCulture();



                        apps/frontend/config/settings.yml
all:
  .settings:
     default_culture: es_ES
$idiomas = $request‐>getLanguages();


$idiomas = $request‐>getPreferredCulture(
  array('en', 'fr')
); 
Incluyendo la cultura 
      en la URL
apps/frontend/config/settings.yml
category:
  url:     /:sf_culture/category/:slug.:sf_format
  class:   sfPropelRoute
  param:   { module: category,
             action: show,
             sf_format: html }
  options: { model: JobeetCategory, type: object }
  requirements:
    sf_format: (?:html|atom)

job_search:
  url:   /:sf_culture/search
  param: { module: job, action: search }
Cambiando de 
   idioma
$ ./symfony plugin:install sfFormExtraPlugin


$ ./symfony cc
apps/frontend/templates/layout.php

<div id=quot;footerquot;>
  <div class=quot;contentquot;>
    <?php include_component('idioma', 'idioma') ?>
  </div>
</div> 




$ ./symfony generate:module frontend idioma
apps/frontend/modules/idioma/actions/components.class.php


class languageComponents extends sfComponents
{
  public function executeIdioma(sfWebRequest $request)
  {
    $this‐>form = new sfFormLanguage(
       $this‐>getUser(),
       array('languages' => array('en', 'fr'))
    );
  }
}
apps/frontend/config/routing.yml
cambiar_idioma:
  url:   /cambiar_idioma
  param: { module: idioma, action: cambiarIdioma }

              apps/frontend/modules/idioma/actions/actions.class.php
class idiomaActions extends sfActions {
  public function executeCambiarIdioma(sfWebRequest $request) {
    $form = new sfFormLanguage(
      $this‐>getUser(),
      array('languages' => array('en', 'fr'))
    );

    $form‐>process($request);

     return $this‐>redirect('@localized_homepage');
    }
}
apps/frontend/config/routing.yml

localized_homepage:
  url:   /:sf_culture/
  param: { module: job, action: index }
  requirements:
    sf_culture: (?:fr|en|es|eu)
Internacionalización
ASCII
Where are you from?



Vous êtes d'où ?      ISO‐8859‐1


どこから来ましたか                 UTF‐8
apps/frontend/config/settings.yml

all:
  .settings:

    charset: utf‐8

    i18n:    on

    standard_helpers: [Partial, Cache, I18N]
apps/frontend/templates/layout.php
<ul>
  <li>
     <a href=quot;quot;><?php echo __('About Jobeet') ?></a> 
  </li>
  <li class=quot;feedquot;>
     <?php echo link_to(__('Full feed'), '@job?sf_format=atom') ?>
  </li>
  <li>
     <a href=quot;quot;><?php echo __('Jobeet API') ?></a> 
  </li>
  <li class=quot;lastquot;>
   <?php echo link_to(__('Become an affiliate'), '@affiliate_new') ?>
  </li>

                            _ _( )           • gettext
</ul>                                                    • SQLite
                                             • MySQL     • XLIFF
$ ./symfony i18n:extract frontend fr ‐‐auto‐save
                                apps/frontend/i18n/fr/messages.xml
<!DOCTYPE xliff PUBLIC quot;‐//XLIFF//DTD XLIFF//ENquot;
quot;http://www.oasis‐open.org/committees/xliff/documents/xliff.dtdquot;>
<xliff version=quot;1.0quot;>
  <file source‐language=quot;ENquot; target‐language=quot;frquot;
        datatype=quot;plaintextquot; original=quot;messagesquot;
        date=quot;2008‐12‐14T12:11:22Zquot; product‐name=quot;messagesquot;>
  <header/>
  <body>
     <trans‐unit id=quot;1quot;>
       <source>About Jobeet</source>
       <target/>
     </trans‐unit>
     <trans‐unit id=quot;2quot;>
       <source>Feed</source>
       <target/>
     </trans‐unit>
    ...
  </body>
  </file>
</xliff>
<div class=quot;more_jobsquot;>
  <?php echo __('and %count% more...', array(
         '%count%' => link_to($count, 'category', $category)
        ))
  ?>
</div>


<?php echo format_number_choice(
  '[0]No job in this category|
   [1]One job in this category|
   (1,+Inf]%count% jobs in this category',
  array(
     '%count%' => '<strong>'.$pager‐>getNbResults().'</strong>'
  ),
  $pager‐>getNbResults()
  )
?>


   $ ./symfony i18n:extract frontend fr ‐‐auto‐save
apps/frontend/i18n/fr/messages.xml

<trans‐unit id=quot;6quot;>
  <source>
    [0]No job in this category|
    [1]One job in this category|
    (1,+Inf]%count% jobs in this category
  </source>
  <target>
    [0]Aucune annonce dans cette catégorie|
    [1]Une annonce dans cette catégorie|
    (1,+Inf]%count% annonces dans cette catégorie
  </target>
</trans‐unit>
config/schema.yml

jobeet_category:
  _attributes: { isI18N: true, i18nTable: 
                 jobeet_category_i18n }
  id:          ~

jobeet_category_i18n:
  id:      { type: integer, required: true, primaryKey: 
             true, foreignTable: jobeet_category, 
             foreignReference: id }
  culture: { isCulture: true, type: varchar, size: 7, 
             required: true, primaryKey: true }
  name:    { type: varchar(255), required: true }
  slug:    { type: varchar(255), required: true }
data/fixtures/010_categories.yml


JobeetCategory:
  design:        { }
  programming:   { }

JobeetCategoryI18n:
  design_en:      { id: design, culture: en, name: Design }
  programming_en: { id: programming, culture: en, name: 
                    Programming }

 design_fr:      { id: design, culture: fr, name: Design }
 programming_fr: { id: programming, culture: fr, name: 
                   Programmation }
apps/frontend/config/routing.yml
category:
 url:     /:sf_culture/category/:slug.:sf_format
 class:   sfPropelRoute
 param:   { module: category, action: show, sf_format: html }
 options: { model: JobeetCategory, type: object, method: 
            doSelectForSlug }
 requirements:
   sf_format: (?:html|atom)



            $ ./symfony propel:data‐load

     /frontend_dev.php/fr/category/programmation
     /frontend_dev.php/en/category/programming
lib/form/JobeetCategoryForm.class.php

class JobeetCategoryForm extends BaseJobeetCategoryForm
{
  public function configure()
  {
    unset($this['jobeet_category_affiliate_list']);

        $this‐>embedI18n(array('en', 'fr'));
        $this‐>widgetSchema‐>setLabel('en', 'English'); 
        $this‐>widgetSchema‐>setLabel('fr', 'French');
    }
}
Localización
format_date()
format_datetime()
format_number()
format_currency()
format_country()
format_language()
sfWidgetFormI18nDate
sfWidgetFormI18nDateTime
sfWidgetFormI18nTime
sfWidgetFormI18nSelectCountry
sfWidgetFormI18nSelectCurrency
sfWidgetFormI18nSelectLanguage
sfValidatorI18nChoiceCountry
sfValidatorI18nChoiceLanguage

More Related Content

What's hot

symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207
patter
 

What's hot (20)

Silex Cheat Sheet
Silex Cheat SheetSilex Cheat Sheet
Silex Cheat Sheet
 
Working With The Symfony Admin Generator
Working With The Symfony Admin GeneratorWorking With The Symfony Admin Generator
Working With The Symfony Admin Generator
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207
 
WordPress REST API hacking
WordPress REST API hackingWordPress REST API hacking
WordPress REST API hacking
 
Symfony2 and AngularJS
Symfony2 and AngularJSSymfony2 and AngularJS
Symfony2 and AngularJS
 
Apigility reloaded
Apigility reloadedApigility reloaded
Apigility reloaded
 
Sylius and Api Platform The story of integration
Sylius and Api Platform The story of integrationSylius and Api Platform The story of integration
Sylius and Api Platform The story of integration
 
PHP 5.3 in practice
PHP 5.3 in practicePHP 5.3 in practice
PHP 5.3 in practice
 
15.exemplu complet eloquent view add-edit-delete-search
15.exemplu complet eloquent view add-edit-delete-search15.exemplu complet eloquent view add-edit-delete-search
15.exemplu complet eloquent view add-edit-delete-search
 
Introduction to Zend framework
Introduction to Zend framework Introduction to Zend framework
Introduction to Zend framework
 
WordPress REST API hacking
WordPress REST API hackingWordPress REST API hacking
WordPress REST API hacking
 
The Enterprise Wor/d/thy/Press
The Enterprise Wor/d/thy/PressThe Enterprise Wor/d/thy/Press
The Enterprise Wor/d/thy/Press
 
PHP MVC
PHP MVCPHP MVC
PHP MVC
 
Building Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJSBuilding Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJS
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBenelux
 
Building Potent WordPress Websites
Building Potent WordPress WebsitesBuilding Potent WordPress Websites
Building Potent WordPress Websites
 
Elixir/OTP for PHP developers
Elixir/OTP for PHP developersElixir/OTP for PHP developers
Elixir/OTP for PHP developers
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better Code
 
And the Greatest of These Is ... Rack Support
And the Greatest of These Is ... Rack SupportAnd the Greatest of These Is ... Rack Support
And the Greatest of These Is ... Rack Support
 
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years laterSymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
 

Viewers also liked

Aplicaciones web altamente escalables con Redis
Aplicaciones web altamente escalables con RedisAplicaciones web altamente escalables con Redis
Aplicaciones web altamente escalables con Redis
Alberto Gimeno
 

Viewers also liked (7)

Desymfony 2011 - Twig
Desymfony 2011 - TwigDesymfony 2011 - Twig
Desymfony 2011 - Twig
 
Desymfony 2011 - Tutorial #1: Instalacion y primeros pasos
Desymfony 2011 - Tutorial #1: Instalacion y primeros pasosDesymfony 2011 - Tutorial #1: Instalacion y primeros pasos
Desymfony 2011 - Tutorial #1: Instalacion y primeros pasos
 
Desymfony 2011 - Introducción a Symfony2
Desymfony 2011 - Introducción a Symfony2Desymfony 2011 - Introducción a Symfony2
Desymfony 2011 - Introducción a Symfony2
 
Aplicaciones web altamente escalables con Redis
Aplicaciones web altamente escalables con RedisAplicaciones web altamente escalables con Redis
Aplicaciones web altamente escalables con Redis
 
Curso Symfony - Clase 3
Curso Symfony - Clase 3Curso Symfony - Clase 3
Curso Symfony - Clase 3
 
Tutorial3 Desymfony - La Vista. Twig
Tutorial3 Desymfony - La Vista. TwigTutorial3 Desymfony - La Vista. Twig
Tutorial3 Desymfony - La Vista. Twig
 
Escalabilidad y alto rendimiento con Symfony2
Escalabilidad y alto rendimiento con Symfony2Escalabilidad y alto rendimiento con Symfony2
Escalabilidad y alto rendimiento con Symfony2
 

Similar to Curso Symfony - Clase 4

OSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialOSDC 2009 Rails Turtorial
OSDC 2009 Rails Turtorial
Yi-Ting Cheng
 
Zend - Installation And Sample Project Creation
Zend - Installation And Sample Project Creation Zend - Installation And Sample Project Creation
Zend - Installation And Sample Project Creation
Compare Infobase Limited
 
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
arcware
 
Intro To Mvc Development In Php
Intro To Mvc Development In PhpIntro To Mvc Development In Php
Intro To Mvc Development In Php
funkatron
 

Similar to Curso Symfony - Clase 4 (20)

OSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialOSDC 2009 Rails Turtorial
OSDC 2009 Rails Turtorial
 
Zend - Installation And Sample Project Creation
Zend - Installation And Sample Project Creation Zend - Installation And Sample Project Creation
Zend - Installation And Sample Project Creation
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
 
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
 
HTML::FormFu talk for Sydney PM
HTML::FormFu talk for Sydney PMHTML::FormFu talk for Sydney PM
HTML::FormFu talk for Sydney PM
 
Magento Live Australia 2016: Request Flow
Magento Live Australia 2016: Request FlowMagento Live Australia 2016: Request Flow
Magento Live Australia 2016: Request Flow
 
Intro To Mvc Development In Php
Intro To Mvc Development In PhpIntro To Mvc Development In Php
Intro To Mvc Development In Php
 
Django - Framework web para perfeccionistas com prazos
Django - Framework web para perfeccionistas com prazosDjango - Framework web para perfeccionistas com prazos
Django - Framework web para perfeccionistas com prazos
 
Gae
GaeGae
Gae
 
Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8
 
Using of TDD practices for Magento
Using of TDD practices for MagentoUsing of TDD practices for Magento
Using of TDD practices for Magento
 
WordPress Plugin development
WordPress Plugin developmentWordPress Plugin development
WordPress Plugin development
 
Ch ch-changes cake php2
Ch ch-changes cake php2Ch ch-changes cake php2
Ch ch-changes cake php2
 
Introduction to CodeIgniter (RefreshAugusta, 20 May 2009)
Introduction to CodeIgniter (RefreshAugusta, 20 May 2009)Introduction to CodeIgniter (RefreshAugusta, 20 May 2009)
Introduction to CodeIgniter (RefreshAugusta, 20 May 2009)
 
Silex Cheat Sheet
Silex Cheat SheetSilex Cheat Sheet
Silex Cheat Sheet
 
More Secrets of JavaScript Libraries
More Secrets of JavaScript LibrariesMore Secrets of JavaScript Libraries
More Secrets of JavaScript Libraries
 
Rugalytics | Ruby Manor Nov 2008
Rugalytics | Ruby Manor Nov 2008Rugalytics | Ruby Manor Nov 2008
Rugalytics | Ruby Manor Nov 2008
 
Framework
FrameworkFramework
Framework
 
Zend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_ToolZend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_Tool
 
Extend sdk
Extend sdkExtend sdk
Extend sdk
 

More from Javier Eguiluz

Twig, el nuevo motor de plantillas de Drupal 8
Twig, el nuevo motor de plantillas de Drupal 8Twig, el nuevo motor de plantillas de Drupal 8
Twig, el nuevo motor de plantillas de Drupal 8
Javier Eguiluz
 
Twig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadasTwig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadas
Javier Eguiluz
 

More from Javier Eguiluz (18)

deSymfony 2017: Symfony 4, Symfony Flex y el futuro de Symfony
deSymfony 2017: Symfony 4, Symfony Flex y el futuro de SymfonydeSymfony 2017: Symfony 4, Symfony Flex y el futuro de Symfony
deSymfony 2017: Symfony 4, Symfony Flex y el futuro de Symfony
 
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
 
Mastering Twig (DrupalCon Barcelona 2015)
Mastering Twig (DrupalCon Barcelona 2015)Mastering Twig (DrupalCon Barcelona 2015)
Mastering Twig (DrupalCon Barcelona 2015)
 
Symfony tips and tricks
Symfony tips and tricksSymfony tips and tricks
Symfony tips and tricks
 
Twig, el nuevo motor de plantillas de Drupal 8
Twig, el nuevo motor de plantillas de Drupal 8Twig, el nuevo motor de plantillas de Drupal 8
Twig, el nuevo motor de plantillas de Drupal 8
 
Silex al límite
Silex al límiteSilex al límite
Silex al límite
 
Twig tips and tricks
Twig tips and tricksTwig tips and tricks
Twig tips and tricks
 
Silex, desarrollo web ágil y profesional con PHP
Silex, desarrollo web ágil y profesional con PHPSilex, desarrollo web ágil y profesional con PHP
Silex, desarrollo web ágil y profesional con PHP
 
Twig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadasTwig, los mejores trucos y técnicas avanzadas
Twig, los mejores trucos y técnicas avanzadas
 
Wallpaper Notifier
Wallpaper NotifierWallpaper Notifier
Wallpaper Notifier
 
Backend (sf2Vigo)
Backend (sf2Vigo)Backend (sf2Vigo)
Backend (sf2Vigo)
 
Twig avanzado (sf2Vigo)
Twig avanzado (sf2Vigo)Twig avanzado (sf2Vigo)
Twig avanzado (sf2Vigo)
 
Desymfony 2012 - Concurso de diseño
Desymfony 2012 - Concurso de diseñoDesymfony 2012 - Concurso de diseño
Desymfony 2012 - Concurso de diseño
 
Desymfony 2011 - Tutorial #5: Backend
Desymfony 2011 - Tutorial #5: BackendDesymfony 2011 - Tutorial #5: Backend
Desymfony 2011 - Tutorial #5: Backend
 
Symfony2, Jornadas Symfony
Symfony2, Jornadas SymfonySymfony2, Jornadas Symfony
Symfony2, Jornadas Symfony
 
Curso Symfony - Anexos
Curso Symfony - AnexosCurso Symfony - Anexos
Curso Symfony - Anexos
 
Curso Symfony - Clase 5
Curso Symfony - Clase 5Curso Symfony - Clase 5
Curso Symfony - Clase 5
 
Curso Symfony - Clase 1
Curso Symfony - Clase 1Curso Symfony - Clase 1
Curso Symfony - Clase 1
 

Recently uploaded

Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 

Recently uploaded (20)

How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 

Curso Symfony - Clase 4