More Related Content Similar to Curso Symfony - Clase 4 (20) More from Javier Eguiluz (18) Curso Symfony - Clase 43. 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/
8. 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]
10. 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();
}
11. 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);
}
}
12. $ ./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());
}
}
18. 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,
))) ?>
21. 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
27. 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');
}
30. 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;
31. 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/
• •
32. 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;
}
}
36. 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”
38. 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;
39. 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/
• •
40. 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;
}
}
42. 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';
}
44. 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();
}
45. 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;
}
}
48. 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);
}
// ...
}
49. 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));
}
53. 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>
55. $('#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();
56. 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') ?>
58. AJAX JavaScript
layout +
layout +
searchSuccess.php
renderPartial()
66. 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
74. 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');
}
}
79. 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
80. $ ./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>
81. <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
82. 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>
83. 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 }
84. 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 }