Symfony 1.4.20 – Database – Form Accesso Dati

Creare automaticamente con Symfony un Form per accedere ai dati del dababase.

In Symfony un progetto è composto da applicazioni suddivise in moduli, ad esempio:

– jobeet/apps/frontend/modules/contenuto
– jobeet/apps/frontend/modules/job
– jobeet/apps/frontend/modules/nome altro modulo …

– jobeet/apps/nome altra app…

1. Generiamo automaticamente il codice php per la gestione di un modulo di nome ‘job’
cmd.exe -> C:\wamp64\www\jobeet>symfony doctrine:generate-module –with-show –non-verbose-templates frontend job JobeetJob

verrà creato automaticamente:

apps/frontend/modules/job/actions/
apps/frontend/modules/job/templates/

in particolare apps/frontend/modules/job/actions/action.class.php


<?php

/**
 * job actions.
 *
 * @package    symfony
 * @subpackage job
 * @author     Your name here
 * @version    SVN: $Id: actions.class.php 23810 2009-11-12 11:07:44Z Kris.Wallsmith $
 */
class jobActions extends sfActions
{
  public function executeIndex(sfWebRequest $request)
  {
    $this->jobeet_jobs = Doctrine_Core::getTable('JobeetJob')
      ->createQuery('a')
      ->execute();
  }

  public function executeShow(sfWebRequest $request)
  {
    $this->jobeet_job = Doctrine_Core::getTable('JobeetJob')->find(array($request->getParameter('id')));
    $this->forward404Unless($this->jobeet_job);
  }

  public function executeNew(sfWebRequest $request)
  {
    $this->form = new JobeetJobForm();
  }

  public function executeCreate(sfWebRequest $request)
  {
    $this->forward404Unless($request->isMethod(sfRequest::POST));

    $this->form = new JobeetJobForm();

    $this->processForm($request, $this->form);

    $this->setTemplate('new');
  }

  public function executeEdit(sfWebRequest $request)
  {
    $this->forward404Unless($jobeet_job = Doctrine_Core::getTable('JobeetJob')->find(array($request->getParameter('id'))), sprintf('Object jobeet_job does not exist (%s).', $request->getParameter('id')));
    $this->form = new JobeetJobForm($jobeet_job);
  }

  public function executeUpdate(sfWebRequest $request)
  {
    $this->forward404Unless($request->isMethod(sfRequest::POST) || $request->isMethod(sfRequest::PUT));
    $this->forward404Unless($jobeet_job = Doctrine_Core::getTable('JobeetJob')->find(array($request->getParameter('id'))), sprintf('Object jobeet_job does not exist (%s).', $request->getParameter('id')));
    $this->form = new JobeetJobForm($jobeet_job);

    $this->processForm($request, $this->form);

    $this->setTemplate('edit');
  }

  public function executeDelete(sfWebRequest $request)
  {
    $request->checkCSRFProtection();

    $this->forward404Unless($jobeet_job = Doctrine_Core::getTable('JobeetJob')->find(array($request->getParameter('id'))), sprintf('Object jobeet_job does not exist (%s).', $request->getParameter('id')));
    $jobeet_job->delete();

    $this->redirect('job/index');
  }

  protected function processForm(sfWebRequest $request, sfForm $form)
  {
    $form->bind($request->getParameter($form->getName()), $request->getFiles($form->getName()));
    if ($form->isValid())
    {
      $jobeet_job = $form->save();
      $this->redirect('job/edit?id='.$jobeet_job->get());
    }
  }
}

Puntare il browser a: http://localhost/jobeet/web/index.php/job per vedere il form in azione

2. Personalizziamo il template a: jobeet/apps/frontend/templates/layout.php


<!-- apps/frontend/templates/layout.php -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Jobeet - Your best job board</title>
    <link rel="shortcut icon" href="/favicon.ico" />
    <?php include_javascripts() ?>
    <?php include_stylesheets() ?>
  </head>
  <body>
    <div id="container">
      <div id="header">
        <div class="content">
          <h1><a href="<?php echo url_for('job/index') ?>">
            <img src="/legacy/images/logo.jpg" alt="Jobeet Job Board" />
          </a></h1>
 
          <div id="sub_header">
            <div class="post">
              <h2>Ask for people</h2>
              <div>
                <a href="<?php echo url_for('job/index') ?>">Post a Job</a>
              </div>
            </div>
 
            <div class="search">
              <h2>Ask for a job</h2>
              <form action="" method="get">
                <input type="text" name="keywords"
                  id="search_keywords" />
                <input type="submit" value="search" />
                <div class="help">
                  Enter some keywords (city, country, position, ...)
                </div>
              </form>
            </div>
          </div>
        </div>
      </div>
 
      <div id="content">
        <?php if ($sf_user->hasFlash('notice')): ?>
          <div class="flash_notice">
            <?php echo $sf_user->getFlash('notice') ?>
          </div>
        <?php endif; ?>
 
        <?php if ($sf_user->hasFlash('error')): ?>
          <div class="flash_notice">
            <?php echo $sf_user->getFlash('error') ?>
          </div>
        <?php endif; ?>
 
        <div class="content">
          <?php echo $sf_content ?>
        </div>
      </div>
 
      <div id="footer">
        <div class="content">
          <span class="symfony">
            <img src="/legacy/images/jobeet-mini.png" />
            powered by <a href="/">
            <img src="/legacy/images/symfony.gif" alt="symfony framework" />
            </a>
          </span>
          <ul>
            <li><a href="">About Jobeet</a></li>
            <li class="feed"><a href="">Full feed</a></li>
            <li><a href="">Jobeet API</a></li>
            <li class="last"><a href="">Affiliates</a></li>
          </ul>
        </div>
      </div>
    </div>
  </body>
</html>

Incompatibilità PHP 5.5

Puntare il browser a: http://localhost/jobeet/web/frontend_dev.php/job

preg_replace() è deprecata, andrebbe sostituita nelle librerie Symfony con preg_replace_callback(), cancelliamo i warning testuali generati nel codice e tentiamo di correggere l’errore (https://gist.github.com/gitllermopalafox/0a8b60eaafede6af0b75)

Correggere C:\wamp64\bin\php\php5.6.25\pear\symfony\response\sfWebResponse.class.php riga 409


protected function normalizeHeaderName($name)
  {
    // return preg_replace('/\-(.)/e', "'-'.strtoupper('\\1')", strtr(ucfirst(strtolower($name)), '_', '-'));    

    return preg_replace_callback(
                  '/\-(.)/', 
                  function ($matches) {
                    return '-'.strtoupper($matches[1]);
                  }, 
                  strtr(ucfirst(strtolower($name)), '_', '-')
        );
  }  

Correggere C:\wamp64\bin\php\php5.6.25\pear\symfony\util\sfToolkit.class.php riga 362:


public static function pregtr($search, $replacePairs)
  {
    // return preg_replace(array_keys($replacePairs), array_values($replacePairs), $search);
    foreach($replacePairs as $pattern => $replacement)
        $search = preg_replace_callback(
                    $pattern, 
                    function ($matches) use ($replacement){
                        if(array_key_exists(1, $matches)){ $replacement = str_replace("\\1", $matches[1], $replacement);}
                        if(array_key_exists(2, $matches)){ $replacement = str_replace("\\2", $matches[2], $replacement);}
                        return $replacement;
                    }, 
                    $search
                );
    return $search;
  }

By |PHP, Symfony, Web Business|Commenti disabilitati su Symfony 1.4.20 – Database – Form Accesso Dati

Symfony 1.4.22 – Contact Form Semplice

Come creare con Symfony 1.4.22 un semplice form per i contatti.

Form dentro al Controller

1. apps/modules/contenuto/actions/actions.class.php


<?php

class contenutoActions extends sfActions // estende la classe Symfony
{
  public function executeContact($request) // crea la pagina http://localhost/jobeet/web/contenuto/contact
    {
      $this->form = new sfForm(); // istanzia la classe di Symfony per la creazione dei form
      // setta i widget, cioè il tipo di campo e i parametri
      $this->form->setWidgets(array(
        'name'    => new sfWidgetFormInputText(),
        'email'   => new sfWidgetFormInputText(array('default' => 'me@example.com')),
        'subject' => new sfWidgetFormChoice(array('choices' => array('Subject A', 'Subject B', 'Subject C'))),
        'message' => new sfWidgetFormTextarea(),
      ));
      // la richiesta inviata a contactSuccess.php sarà un oggetto composto da array
      // l'oggetto è contenuto nella variabile  - form - in contactSuccess.php sarà - echo $form -
    }
}// END class

2. apps/modules/contenuto/templates/contactSuccess.php


<?php echo $form->renderFormTag('contenuto/contact') ?>
  <table>
    <?php echo $form ?>
    <tr>
      <td colspan="2">
        <input type="submit" />
      </td>
    </tr>
  </table>
</form>

3. Puntare il browser a: http://localhost/jobeet/web/frontend_dev.php/contenuto/contact


<form action="/frontend_dev.php/contenuto/contact" method="POST">
  <table>
    <tr>
      <th><label for="name">Name</label></th>
      <td><input type="text" name="name" id="name" /></td>
    </tr>
    <tr>
      <th><label for="email">Email</label></th>
      <td><input type="text" name="email" id="email" value="me@example.com" /></td>
    </tr>
    <tr>
      <th><label for="subject">Subject</label></th>
      <td>
        <select name="subject" id="subject">
          <option value="0">Subject A</option>
          <option value="1">Subject B</option>
          <option value="2">Subject C</option>
        </select>
      </td>
    </tr>
    <tr>
      <th><label for="message">Message</label></th>
      <td><textarea rows="4" cols="30" name="message" id="message"></textarea></td>
    </tr>
    <tr>
      <td colspan="2">
        <input type="submit" />
      </td>
    </tr>
  </table>
</form>

Reference:
http://symfony.com/legacy/doc/gentle-introduction/1_4/it/10-forms

By |PHP, Symfony, Web Design|Commenti disabilitati su Symfony 1.4.22 – Contact Form Semplice

Symfony 1.4.22 – Layout

Il layout contiene gli elementi HTML comuni a tutte le pagine del sito.
La struttura finale del sito sarà composta dalla combinazione layout + template.

Il layout in Symfony 1.4.22 è il file in:
jobeet/apps/frontend/templates/layout.php


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <?php include_http_metas() ?>
    <?php include_metas() ?>
    <?php include_title() ?>
    <link rel="shortcut icon" href="/favicon.ico" />
    <?php include_stylesheets() ?>
    <?php include_javascripts() ?>
  </head>
  <body>
    <?php echo $sf_content ?>
  </body>
</html>

La parte più interessante è:


<?php echo $sf_content ?>

La variabile $sf_content contiene HTML generato dall’azione di Symfony.

Di default, il task generate:project ha creato tre cartelle per i file degli elementi grafici:
– web/images/
– web/css/
– web/js/

In Symfony è possibile definire diversi layout, vediamo un esempio pratico.

actions.class.php


<?php
 
class contenutoActions extends sfActions // estende la classe Symfony
{ 
  public function executePageone() // http://localhost/jobeet/web/frontend_dev.php/contenuto/pageone
  {
  }
   public function executePagetwo() // http://localhost/jobeet/web/frontend_dev.php/contenuto/pagetwo
  {
      $this->setLayout('mio_layout');
  }
}// END class

pageoneSuccess.php


Page One Success

pagetwoSuccess.php


Page Two Success

layout.php


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <?php include_http_metas() ?>
    <?php include_metas() ?>
    <?php include_title() ?>
    <link rel="shortcut icon" href="/favicon.ico" />
    <?php include_stylesheets() ?>
    <?php include_javascripts() ?>
  </head>
  <body>
    Layout di default
    <?php echo $sf_content ?>
  </body>
</html>

mio_layout.php


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <?php include_http_metas() ?>
    <?php include_metas() ?>
    <?php include_title() ?>
    <link rel="shortcut icon" href="/favicon.ico" />
    <?php include_stylesheets() ?>
    <?php include_javascripts() ?>
  </head>
  <body>
    Mio Layout
    <?php echo $sf_content ?>
  </body>
</html>

Puntare il browser a:

– http://localhost/jobeet/web/frontend_dev.php/contenuto/pageone
Renderizza:
Layout di default Page One Success

– http://localhost/jobeet/web/frontend_dev.php/contenuto/pagetwo
Renderizza:
Mio Layout Page Two Success

Reference:
http://symfony.com/legacy/doc/jobeet/1_4/it/04?orm=Doctrine

By |PHP, Symfony, Web Design|Commenti disabilitati su Symfony 1.4.22 – Layout

Symfony 1.4.20 – Ripulire la Cache

Ogni volta che creiamo delle nuovre classi dovremo ripulire la cache per permettere a Symfony di utilizzare il nuovo codice creato.

Per ripulire la cache:
cmd.exe -> C:\wamp64\www\jobeet>symfony cache:clear

By |PHP, Symfony, Web Design|Commenti disabilitati su Symfony 1.4.20 – Ripulire la Cache

Creare un Database – ORM – Doctrine

La gestione del database su Symfony è di tipo ORM (Object-relational mapping), cioè òegge e scrive dal database utilizzando un’interfaccia orientata agli oggetti.

Symfony dispone di due ORM Propel e Doctrine.

L’ORM ha bisogno della descrizione delle tabelle e delle loro relazioni per creare le relative classi, quindi descriviamo il tutto in un file YAML.

1. C:\wamp64\www\jobeet\config\doctrine\schema.yml
Qui descriviamo in formato YML le tabelle e le colonne del DB

NB: in YAML l’indentazione deve essere fatta con uno o più spazi, mai con le tabulazioni.


# config/doctrine/schema.yml
JobeetCategory:
  actAs: { Timestampable: ~ }
  columns:
    name: { type: string(255), notnull: true, unique: true }
 
JobeetJob:
  actAs: { Timestampable: ~ }
  columns:
    category_id:  { type: integer, notnull: true }
    type:         { type: string(255) }
    company:      { type: string(255), notnull: true }
    logo:         { type: string(255) }
    url:          { type: string(255) }
    position:     { type: string(255), notnull: true }
    location:     { type: string(255), notnull: true }
    description:  { type: string(4000), notnull: true }
    how_to_apply: { type: string(4000), notnull: true }
    token:        { type: string(255), notnull: true, unique: true }
    is_public:    { type: boolean, notnull: true, default: 1 }
    is_activated: { type: boolean, notnull: true, default: 0 }
    email:        { type: string(255), notnull: true }
    expires_at:   { type: timestamp, notnull: true }
  relations:
    JobeetCategory: { onDelete: CASCADE, local: category_id, foreign: id, foreignAlias: JobeetJobs } 
 
JobeetAffiliate:
  actAs: { Timestampable: ~ }
  columns:
    url:       { type: string(255), notnull: true }
    email:     { type: string(255), notnull: true, unique: true }
    token:     { type: string(255), notnull: true }
    is_active: { type: boolean, notnull: true, default: 0 }
  relations:
    JobeetCategories:
      class: JobeetCategory
      refClass: JobeetCategoryAffiliate
      local: affiliate_id
      foreign: category_id
      foreignAlias: JobeetAffiliates
 
JobeetCategoryAffiliate:
  columns:
    category_id:  { type: integer, primary: true }
    affiliate_id: { type: integer, primary: true }
  relations:
    JobeetCategory:  { onDelete: CASCADE, local: category_id, foreign: id }
    JobeetAffiliate: { onDelete: CASCADE, local: affiliate_id, foreign: id }

L’attributo onDelete definisce il comportamento ON DELETE delle chiavi esterne, Doctrine supporta CASCADE, SET NULL e RESTRICT. Per esempio quando un record job viene eliminato, tutti i record jobeet_category_affiliate associati verranno automaticamente eliminati dal database.

2. Aprire PhpMyAdmin> Nuovo> Crea un nuovo database> jobeet

3. Indichiamo a Symfony di utilizzare il database jobeet, supponendo che il nostro DB non abbia bisogno di password:
cmd.exe -> C:\wamp64\www\jobeet>symfony configure:database “mysql:host=localhost;dbname=jobeet”

Il task configure:database salva la configurazione all’interno del file jobeet/config/databases.yml:


all:
  doctrine:
    class: sfDoctrineDatabase
    param:
      dsn: 'mysql:host=localhost;dbname=jobeet'
      username: root
      password: null

4. Crezione dei modelli cioè delle classi PHP per la gestione del DB:
cmd.exe -> C:\wamp64\www\jobeet>symfony doctrine:build –model

Crea i file php con le classi per la gestione del DB in jobeet/lib/model/doctrine/
– JobeetAffiliate.class.php
– JobeetAffiliateTable.class.php
– etc…

Il DB è ancora vuoto, non ha tabelle ne colonne

5. Generazione dei comandi SQL
cmd.exe -> C:\wamp64\www\jobeet>symfony doctrine:build –sql

Genera il file jobeet/data/sql/schema.sql:


CREATE TABLE jobeet_affiliate (id BIGINT AUTO_INCREMENT, url VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL UNIQUE, token VARCHAR(255) NOT NULL, is_active TINYINT(1) DEFAULT '0' NOT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, PRIMARY KEY(id)) ENGINE = INNODB;
CREATE TABLE jobeet_category (id BIGINT AUTO_INCREMENT, name VARCHAR(255) NOT NULL UNIQUE, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, PRIMARY KEY(id)) ENGINE = INNODB;
CREATE TABLE jobeet_category_affiliate (category_id BIGINT, affiliate_id BIGINT, PRIMARY KEY(category_id, affiliate_id)) ENGINE = INNODB;
CREATE TABLE jobeet_job (id BIGINT AUTO_INCREMENT, category_id BIGINT NOT NULL, type VARCHAR(255), company VARCHAR(255) NOT NULL, logo VARCHAR(255), url VARCHAR(255), position VARCHAR(255) NOT NULL, location VARCHAR(255) NOT NULL, description TEXT NOT NULL, how_to_apply TEXT NOT NULL, token VARCHAR(255) NOT NULL UNIQUE, is_public TINYINT(1) DEFAULT '1' NOT NULL, is_activated TINYINT(1) DEFAULT '0' NOT NULL, email VARCHAR(255) NOT NULL, expires_at DATETIME NOT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, INDEX category_id_idx (category_id), PRIMARY KEY(id)) ENGINE = INNODB;
ALTER TABLE jobeet_category_affiliate ADD CONSTRAINT jobeet_category_affiliate_category_id_jobeet_category_id FOREIGN KEY (category_id) REFERENCES jobeet_category(id) ON DELETE CASCADE;
ALTER TABLE jobeet_category_affiliate ADD CONSTRAINT jobeet_category_affiliate_affiliate_id_jobeet_affiliate_id FOREIGN KEY (affiliate_id) REFERENCES jobeet_affiliate(id) ON DELETE CASCADE;
ALTER TABLE jobeet_job ADD CONSTRAINT jobeet_job_category_id_jobeet_category_id FOREIGN KEY (category_id) REFERENCES jobeet_category(id) ON DELETE CASCADE;

Il DB è ancora vuoto, non ha tabelle ne colonne

6. Eseguiamo schema.sql nel DB
cmd.exe -> C:\wamp64\www\jobeet>symfony doctrine:insert-sql

Aprire PhpMyAdmin, ora il database ha tabelle e colonne

7. Ripuliamo la cache per permettere a Symfony di utilizzare le nuove classi creare con la creazione dei modelli
cmd.exe -> C:\wamp64\www\jobeet>symfony cache:clear

Reference:
http://symfony.com/legacy/doc/jobeet/1_4/it/03?orm=Doctrine

By |PHP, Symfony, Web Design|Commenti disabilitati su Creare un Database – ORM – Doctrine