PageRenderTime 28ms CodeModel.GetById 2ms app.highlight 21ms RepoModel.GetById 1ms app.codeStats 0ms

/jobeet/it/14.markdown

https://github.com/rafaelgou/symfony1-docs
Markdown | 418 lines | 347 code | 71 blank | 0 comment | 0 complexity | 82207d338a519e7b44f29a2010a73ffa MD5 | raw file
  1Giorno 14: Feed
  2===============
  3
  4Ieri avete iniziato a sviluppare la vostra prima applicazione con symfony.
  5Non fermatevi adesso. Come imparate qualcosa di nuovo su symfony provate
  6ad aggiungere nuove feature alla vostra applicazione, rendetela pubblica
  7e condividetela con la comunità.
  8
  9Passiamo oggi a qualcosa di completamente diverso.
 10
 11Se state cercando un lavoro molto probabilmente vorreste essere informati
 12ogni volta che un'offerta viene inserita. Poiché controllare il sito web
 13ogni ora non è molto conveniente, oggi aggiungeremo molti feed, per tenere
 14aggiornati gli utenti di Jobeet.
 15
 16Formati
 17-------
 18
 19Il framework symfony ha un supporto nativo per ~formati|Formati~ e ~tipi mime|Tipi mime~. Questo 
 20significa che gli stessi Model e Controller possono avere diversi ~template|Template~
 21in base al formato richiesto. Il formato di default è HTML, tuttavia symfony
 22supporta molti altri ~formati in modo nativo|Formati nativi~ come `txt`, `js`, `css`, `json`, 
 23`xml`, `rdf` o `atom`.
 24
 25Il formato può essere impostato usando il metodo `setRequestFormat()`
 26dell'oggetto ~richiesta|Richiesta HTTP~:
 27
 28    [php]
 29    $request->setRequestFormat('xml');
 30
 31
 32Il più delle volte il formato è integrato nell'URL. In questo caso symfony
 33lo imposterà per voi se la variabile speciale ~`sf_format`~ è utilizzata
 34nella corrispondente rotta. Per la lista delle offerte l'URL è:
 35
 36    http://jobeet.localhost/frontend_dev.php/job
 37
 38Questo URL è equivalente a:
 39
 40    http://jobeet.localhost/frontend_dev.php/job.html
 41
 42Entrambi gli URL sono equivalenti perché le rotte generate dalla classe 
 43`sfPropelRouteCollection` hanno `sf_format` come estensione e perché
 44il formato standard è `html`. Potete verificarlo personalmente
 45utilizzando il task `app:routes`.
 46
 47![Cli](http://www.symfony-project.org/images/jobeet/1_4/15/cli.png)
 48
 49Feed
 50----
 51
 52### Feed Ultime Offerte di Lavoro
 53
 54Supportare diversi formati è semplice quanto creare diversi template. Per
 55creare un [Atom feed](http://en.wikipedia.org/wiki/Atom_(standard)) per
 56le ultime offerte inserite, create il template `indexSuccess.atom.php`:
 57
 58    [php]
 59    <!-- apps/frontend/modules/job/templates/indexSuccess.atom.php -->
 60    <?xml version="1.0" encoding="utf-8"?>
 61    <feed xmlns="http://www.w3.org/2005/Atom">
 62      <title>Jobeet</title>
 63      <subtitle>Latest Jobs</subtitle>
 64      <link href="" rel="self"/>
 65      <link href=""/>
 66      <updated></updated>
 67      <author><name>Jobeet</name></author>
 68      <id>Unique Id</id>
 69
 70      <entry>
 71        <title>Job title</title>
 72        <link href="" />
 73        <id>Unique id</id>
 74        <updated></updated>
 75        <summary>Job description</summary>
 76        <author><name>Company</name></author>
 77      </entry>
 78    </feed>
 79
 80>**SIDEBAR**
 81>Nomi dei template
 82>
 83>Siccome `html` è il formato più comune per le applicazioni web può essere
 84>omesso dai nomi dei template. Sia `indexSuccess.php` che `indexSuccess.html.php`
 85>sono equivalenti e symfony usa il primo che trova.
 86>
 87>Perché i template di default hanno come suffisso `Success`? Un'azione può restituire
 88>un valore per indicare quale template usare. Se l'azione non restituisce nulla,
 89>è equivalente al seguente codice:
 90>
 91>     [php]
 92>     return sfView::SUCCESS; // == 'Success'
 93>
 94>Se volete cambiare il suffisso basta tornare qualcosa di diverso:
 95>
 96>     [php]
 97>     return sfView::ERROR; // == 'Error'
 98>
 99>     return 'Foo';
100>
101>Come abbiamo visto in un giorno precedente, si può inoltre cambiare il
102>nome del template usando il metodo `setTemplate()`:
103>
104>     [php]
105>     $this->setTemplate('foo');
106
107Di default symfony cambia la risposta `~Content-Type~` in accordo al formato, 
108per tutti i formati non-HTML il layout viene disabilitato. Per un feed Atom
109symfony cambia il `Content-Type` a `application/atom+xml; charset=utf-8`.
110
111Nel footer di Jobeet aggiornate il link del feed:
112
113    [php]
114    <!-- apps/frontend/templates/layout.php -->
115    <li class="feed">
116      <a href="<?php echo url_for('@job?sf_format=atom') ?>">Full feed</a>
117    </li>
118
119L'~URI interno~ è lo stesso che per la lista `job` con il `sf_format` aggiunto
120come variabile.
121
122Aggiungete un `<link>` tag nell'head del layout, per consentire la
123scoperta automatica dei feed da parte del browser:
124
125    [php]
126    <!-- apps/frontend/templates/layout.php -->
127    <link rel="alternate" type="application/atom+xml" title="Latest Jobs"
128      href="<?php echo url_for('@job?sf_format=atom', true) ?>" />
129
130Per l'attributo `href` link viene usato un ~URL assoluto~, grazie al secondo
131parametro dell'helper `url_for()`.
132
133Sostituiamo l'header del template Atom col codice seguente:
134
135    [php]
136    <!-- apps/frontend/modules/job/templates/indexSuccess.atom.php -->
137    <title>Jobeet</title>
138    <subtitle>Latest Jobs</subtitle>
139    <link href="<?php echo url_for('@job?sf_format=atom', true) ?>" rel="self"/>
140    <link href="<?php echo url_for('@homepage', true) ?>"/>
141<propel>
142    <updated><?php echo gmstrftime('%Y-%m-%dT%H:%M:%SZ', JobeetJobPeer::getLatestPost()->getCreatedAt('U')) ?></updated>
143</propel>
144<doctrine>
145    <updated><?php echo gmstrftime('%Y-%m-%dT%H:%M:%SZ', Doctrine::getTable('JobeetJob')->getLatestPost()->getDateTimeObject('created_at')->format('U')) ?></updated>
146</doctrine>
147    <author>
148      <name>Jobeet</name>
149    </author>
150    <id><?php echo sha1(url_for('@job?sf_format=atom', true)) ?></id>
151
152<propel>
153Notate l'utilizzo di `U` come parametro di `getCreatedAt()` per ottenere la
154data come timestamp. Per avere la data dell'ultimo post, create il metodo
155`getLatestPost()`:
156</propel>
157<doctrine>
158Notate l'utilizzo di `U` come parametro di `format()` per ottenere
159la data come timestamp. Per avere la data dell'ultimo post, create il metodo
160`getLatestPost()`:
161</doctrine>
162
163<propel>
164    [php]
165    // lib/model/JobeetJobPeer.php
166    class JobeetJobPeer extends BaseJobeetJobPeer
167    {
168      static public function getLatestPost()
169      {
170        $criteria = new Criteria();
171        self::addActiveJobsCriteria($criteria);
172
173        return JobeetJobPeer::doSelectOne($criteria);
174      }
175
176      // ...
177    }
178</propel>
179<doctrine>
180    [php]
181    // lib/model/doctrine/JobeetJobTable.class.php
182    class JobeetJobTable extends Doctrine_Table
183    {
184      public function getLatestPost()
185      {
186        $q = Doctrine_Query::create()
187          ->from('JobeetJob j');
188        $this->addActiveJobsCriteria($q);
189
190        return $q->fetchOne();
191      }
192
193      // ...
194    }
195</doctrine>
196
197I dati del feed possono essere generati con il seguente codice:
198
199    [php]
200    <!-- apps/frontend/modules/job/templates/indexSuccess.atom.php -->
201    <?php use_helper('Text') ?>
202    <?php foreach ($categories as $category): ?>
203      <?php foreach ($category->getActiveJobs(sfConfig::get('app_max_jobs_on_homepage')) as $job): ?>
204        <entry>
205          <title>
206            <?php echo $job->getPosition() ?> (<?php echo $job->getLocation() ?>)
207          </title>
208          <link href="<?php echo url_for('job_show_user', $job, true) ?>" />
209          <id><?php echo sha1($job->getId()) ?></id>
210<propel>
211          <updated><?php echo gmstrftime('%Y-%m-%dT%H:%M:%SZ', $job->getCreatedAt('U')) ?></updated>
212</propel>
213<doctrine>
214          <updated><?php echo gmstrftime('%Y-%m-%dT%H:%M:%SZ', $job->getDateTimeObject('created_at')->format('U')) ?></updated>
215</doctrine>
216          <summary type="xhtml">
217           <div xmlns="http://www.w3.org/1999/xhtml">
218             <?php if ($job->getLogo()): ?>
219               <div>
220                 <a href="<?php echo $job->getUrl() ?>">
221                   <img src="http://<?php echo $sf_request->getHost().'/uploads/jobs/'.$job->getLogo() ?>"
222                     alt="<?php echo $job->getCompany() ?> logo" />
223                 </a>
224               </div>
225             <?php endif; ?>
226
227             <div>
228               <?php echo simple_format_text($job->getDescription()) ?>
229             </div>
230
231             <h4>How to apply?</h4>
232
233             <p><?php echo $job->getHowToApply() ?></p>
234           </div>
235          </summary>
236          <author>
237            <name><?php echo $job->getCompany() ?></name>
238          </author>
239        </entry>
240      <?php endforeach; ?>
241    <?php endforeach; ?>
242
243Il metodo `getHost()` dell'oggetto request (`$sf_request`) restituisce
244l'host corrente, che torna utile per creare un link assoluto per il
245logo della società.
246
247![Feed](http://www.symfony-project.org/images/jobeet/1_4/15/feed.png)
248
249>**TIP**
250>Creando un feed, il ~debug|Debug~ è più semplice se si usano gli strumenti da
251>linea di comando come 
252>[`curl`](http://curl.haxx.se/) o
253>[`wget`](http://www.gnu.org/software/wget/), in modo da vedere
254>l'attuale contenuto del feed.
255
256### Feed delle ultime offerte in una categoria
257
258Uno degli scopi  di Jobeet è quello di aiutare le persone a trovare lavori
259più specializzati. Quindi abbiamo bisogno di fornire un ~feed|Feed~ per ogni categoria.
260
261Primo, aggiorniamo la rotta `category` per aggiungere il supporto per i 
262differenti formati:
263
264    [yml]
265    // apps/frontend/config/routing.yml
266    category:
267      url:     /category/:slug.:sf_format
268      class:   sfPropelRoute
269      param:   { module: category, action: show, sf_format: html }
270      options: { model: JobeetCategory, type: object }
271      requirements:
272        sf_format: (?:html|atom)
273
274Ora la rotta `category` può capire entrambi i formati `html` e `atom`.
275Aggiornate i link ai feed di categoria nei ~template|Template~:
276
277    [php]
278    <!-- apps/frontend/modules/job/templates/indexSuccess.php -->
279    <div class="feed">
280      <a href="<?php echo url_for('category', array('sf_subject' => $category, 'sf_format' => 'atom')) ?>">Feed</a>
281    </div>
282
283    <!-- apps/frontend/modules/category/templates/showSuccess.php -->
284    <div class="feed">
285      <a href="<?php echo url_for('category', array('sf_subject' => $category, 'sf_format' => 'atom')) ?>">Feed</a>
286    </div>
287
288L'ultimo passo è creare il template `showSuccess.atom.php`. Ma visto che 
289questo feed dovrà elencare le offerte di lavoro possiamo ~rifattorizzare|Rifattorizzare~
290il codice che genera i dati per il feed creando un partial `_list.atom.php`.
291Come per il formato `html` i ~partial|Partial~ sono specifici per il formato:
292
293    [php]
294    <!-- apps/frontend/modules/job/templates/_list.atom.php -->
295    <?php use_helper('Text') ?>
296
297    <?php foreach ($jobs as $job): ?>
298      <entry>
299        <title><?php echo $job->getPosition() ?> (<?php echo $job->getLocation() ?>)</title>
300        <link href="<?php echo url_for('job_show_user', $job, true) ?>" />
301        <id><?php echo sha1($job->getId()) ?></id>
302<propel>
303          <updated><?php echo gmstrftime('%Y-%m-%dT%H:%M:%SZ', $job->getCreatedAt('U')) ?></updated>
304</propel>
305<doctrine>
306          <updated><?php echo gmstrftime('%Y-%m-%dT%H:%M:%SZ', strtotime($job->getCreatedAt())) ?></updated>
307</doctrine>
308        <summary type="xhtml">
309         <div xmlns="http://www.w3.org/1999/xhtml">
310           <?php if ($job->getLogo()): ?>
311             <div>
312               <a href="<?php echo $job->getUrl() ?>">
313                 <img src="http://<?php echo $sf_request->getHost().$job->getLogo() ?>" alt="<?php echo $job->getCompany() ?> logo" />
314               </a>
315             </div>
316           <?php endif; ?>
317
318           <div>
319             <?php echo simple_format_text($job->getDescription()) ?>
320           </div>
321
322           <h4>How to apply?</h4>
323
324           <p><?php echo $job->getHowToApply() ?></p>
325         </div>
326        </summary>
327        <author>
328          <name><?php echo $job->getCompany() ?></name>
329        </author>
330      </entry>
331    <?php endforeach; ?>
332
333Potete usare il partial `_list.atom.php` per semplificare il template del feed
334delle offerte:
335
336    [php]
337    <!-- apps/frontend/modules/job/templates/indexSuccess.atom.php -->
338    <?xml version="1.0" encoding="utf-8"?>
339    <feed xmlns="http://www.w3.org/2005/Atom">
340      <title>Jobeet</title>
341      <subtitle>Latest Jobs</subtitle>
342      <link href="<?php echo url_for('@job?sf_format=atom', true) ?>" rel="self"/>
343      <link href="<?php echo url_for('@homepage', true) ?>"/>
344<propel>
345      <updated><?php echo gmstrftime('%Y-%m-%dT%H:%M:%SZ', JobeetJobPeer::getLatestPost()->getCreatedAt('U')) ?></updated>
346</propel>
347<doctrine>
348      <updated><?php echo gmstrftime('%Y-%m-%dT%H:%M:%SZ', Doctrine::getTable('JobeetJob')->getLatestPost()->getDateTimeObject('created_at')->format('U')) ?></updated>
349</doctrine>
350      <author>
351        <name>Jobeet</name>
352      </author>
353      <id><?php echo sha1(url_for('@job?sf_format=atom', true)) ?></id>
354
355    <?php foreach ($categories as $category): ?>
356      <?php include_partial('job/list', array('jobs' => $category->getActiveJobs(sfConfig::get('app_max_jobs_on_homepage')))) ?>
357    <?php endforeach; ?>
358    </feed>
359
360Infine create il template `showSuccess.atom.php`:
361
362    [php]
363    <!-- apps/frontend/modules/category/templates/showSuccess.atom.php -->
364    <?xml version="1.0" encoding="utf-8"?>
365    <feed xmlns="http://www.w3.org/2005/Atom">
366      <title>Jobeet (<?php echo $category ?>)</title>
367      <subtitle>Latest Jobs</subtitle>
368      <link href="<?php echo url_for('category', array('sf_subject' => $category, 'sf_format' => 'atom'), true) ?>" rel="self" />
369      <link href="<?php echo url_for('category', array('sf_subject' => $category), true) ?>" />
370<propel>
371      <updated><?php echo gmstrftime('%Y-%m-%dT%H:%M:%SZ', $category->getLatestPost()->getCreatedAt('U')) ?></updated>
372</propel>
373<doctrine>
374      <updated><?php echo gmstrftime('%Y-%m-%dT%H:%M:%SZ', $category->getLatestPost()->getDateTimeObject('created_at')->format('U')) ?></updated>
375</doctrine>
376      <author>
377        <name>Jobeet</name>
378      </author>
379      <id><?php echo sha1(url_for('category', array('sf_subject' => $category), true)) ?></id>
380
381      <?php include_partial('job/list', array('jobs' => $pager->getResults())) ?>
382    </feed>
383
384Come per il feed principale abbiamo bisogno della data dell'ultima offerta inserita
385per una categoria:
386
387    [php]
388<propel>
389    // lib/model/JobeetCategory.php
390</propel>
391<doctrine>
392    // lib/model/doctrine/JobeetCategory.class.php
393</doctrine>
394    class JobeetCategory extends BaseJobeetCategory
395    {
396      public function getLatestPost()
397      {
398        $jobs = $this->getActiveJobs(1);
399
400        return $jobs[0];
401      }
402
403      // ...
404    }
405
406![Category Feed](http://www.symfony-project.org/images/jobeet/1_4/15/category_feed.png)
407
408A domani
409--------
410
411Come per molte feature di symfony il supporto nativo vi permette di aggiungere
412feed al proprio sito, senza particolari sforzi.
413
414Oggi abbiamo migliorato l'esperienza di ricerca di lavoro. Domani vedremo come
415dare maggiore possibilità di inserimento a chi pubblica offerte di lavoro 
416fornendo un Web Service.
417
418__ORM__