Quando for necessário criar uma verificação especifica para um dos campos do formulário basta-nos personalizar a validação do(s) campo(s) da seguinte forma:
FormularioForm.class.php
public function configure() {
parent::configure();
$this->validatorSchema['my_field'] = new sfValidatorCallback(
array('callback' =>
array($this, 'validateMyField')
)
);
}
public function validateMyField($validator, $value) {
/* All my action goes here */
if($is_everything_ok){
return $value;
}else{
return new sfValidatorError($validator, "I guess something goes wrong here!");
}
}
Et voilá...
15 de junho de 2011
14 de junho de 2011
Propel, extender schema de plugins
Quando precisamos de adicionar campos novos a uma tabela gerada por um plugin temos que criar um myPlugin_schema.custom.yml onde myPlugin é o nome do plugin.
Caso prático: Adicionar o campo 'coisas' na tabela sf_guard_user (gerada pelo plugin sfGuardPlugin)
1 - criar o ficheiro sfGuardPlugin_schema.custom.yml em project/config/
2 - fazer re-build das classes
Done!
Caso prático: Adicionar o campo 'coisas' na tabela sf_guard_user (gerada pelo plugin sfGuardPlugin)
1 - criar o ficheiro sfGuardPlugin_schema.custom.yml em project/config/
propel: _attributes: { package: plugins.sfGuardPlugin.lib.model } ## # extending sfGuard ## sf_guard_user: _attributes: { phpName: sfGuardUser } coisas: { type: varchar, size: 128, required: true }
2 - fazer re-build das classes
php symfony propel:build --all-classes
Done!
13 de junho de 2011
Servir documentos através de uma action
Por vezes, torna-se necessários servir ficheiros privados, que em vez de estarem no diretório público web/uploads, devem ficar fora de web, impedindo o acesso direto, cabendo a uma action verificar se o utilizador tem permissões e então entregar o ficheiro. Eis como o fazer através do object sfResponse numa action:
public function executeBackup(sfWebRequest $request)
{
// realizar backup da base de dados e dos uploads
$this->setLayout(false);
$this->setTemplate(false);
sfConfig::set('sf_web_debug', false);
// nome do ficheiro tem de coincidir com o definido na task uacBackupTask
$file_cache = sfConfig::get('sf_data_dir').'/backup/backup_'.date('Y-m-d').'.zip';
// verificar se existe ficheiro de backup criado pela task, se sim, entrega esse, senão gera novo
if (file_exists($file_cache))
{
$file = $file_cache;
}
else
{
$file = adcBackup::execute(); // cria o ficheiro e envia o caminho absoluto
$backup = sfConfig::get('sf_data_dir').'/backup/'.basename($file);
@copy($file, $backup);
@chmod($backup, 0666);
}
// check if the file exists
$this->forward404Unless(file_exists($file));
// Adding the file to the Response object
$this->getResponse()->clearHttpHeaders();
$this->getResponse()->addCacheControlHttpHeader('Cache-control','must-revalidate, post-check=0, pre-check=0');
$this->getResponse()->setHttpHeader('Pragma: public', true);
$this->getResponse()->setContentType('application/zip');
$this->getResponse()->setHttpHeader('Content-Disposition','attachment; filename='.basename($file), true);
$this->getResponse()->sendHttpHeaders();
$this->getResponse()->setContent(file_get_contents($file));
return sfView::NONE;
}
public function executeBackup(sfWebRequest $request)
{
// realizar backup da base de dados e dos uploads
$this->setLayout(false);
$this->setTemplate(false);
sfConfig::set('sf_web_debug', false);
// nome do ficheiro tem de coincidir com o definido na task uacBackupTask
$file_cache = sfConfig::get('sf_data_dir').'/backup/backup_'.date('Y-m-d').'.zip';
// verificar se existe ficheiro de backup criado pela task, se sim, entrega esse, senão gera novo
if (file_exists($file_cache))
{
$file = $file_cache;
}
else
{
$file = adcBackup::execute(); // cria o ficheiro e envia o caminho absoluto
$backup = sfConfig::get('sf_data_dir').'/backup/'.basename($file);
@copy($file, $backup);
@chmod($backup, 0666);
}
// check if the file exists
$this->forward404Unless(file_exists($file));
// Adding the file to the Response object
$this->getResponse()->clearHttpHeaders();
$this->getResponse()->addCacheControlHttpHeader('Cache-control','must-revalidate, post-check=0, pre-check=0');
$this->getResponse()->setHttpHeader('Pragma: public', true);
$this->getResponse()->setContentType('application/zip');
$this->getResponse()->setHttpHeader('Content-Disposition','attachment; filename='.basename($file), true);
$this->getResponse()->sendHttpHeaders();
$this->getResponse()->setContent(file_get_contents($file));
return sfView::NONE;
}
8 de junho de 2011
symfony & Doctrine behavior review
The Doctrine ORM is bundled with several behaviors (calles core behaviors), these are:
http://symfony-world.blogspot.com/2010/10/symfonydoctrine-behavior-review.html
- Versionable - add an entire XxxVersion table to store your Xxx model object versions as either only version numbers or numbers versions along with ALL column data - to see object data changes through time,
- Timestampable - probably the most popular of all behaviors, adds created_at and updated_at timestamp columns to your model, automatically saving datetime when a record is created or updated, respecticely,
- Sluggable - adds a slug column that stores a slug which is a unique index automatically and can be used along with sfDoctrineRoute class to refer to an object without passing its ID as a parameter; by default the update is disabled, since this may harm your search engines rating,
- I18n - add an entire XxxTranslation table to provide Internationalization (I18n) for your Xxx model, essential when developing a multi-language project,
- NestedSet - adds root_id, lft, rgt and level columns to your model to develop an advanced hierarchical data structure (such as product categories), nested sets is an alternative to adjacency model, more details on hierarchical data here,
- Searchable - choose model columns you want to index and add an entire database table, speeding up a basic search engine development, more info about searching here,
- Geographical - adds longitude and latitude columns storing geographical coordinates. Ever needed to use gmaps in your project, along with sfEasyGMapPlugin? Not only this behavior suits the data structure you need, but also provides you with getDistance() method to calculate distance between two Geographical objects,
- SoftDelete - adds a deleted_at column which defines if a record has been marked as deleted (and if so, when). Useful when designing a highly complicated system where data consistency is important and even if some data should be invisible in the backend, it should still remain in the database.
extension behaviors
You may also use Doctrine extensions:
- Blameable - adds an additional level of auditing capabilities to models, blameable allows you to track who created or last updated any model in an environment with many users, blameable is a great companion to Timestampable behavior,
- EventLoggable, readme - logs any Doctrine Events (pre/post Delete/Insert/...) fired upon a record, log type may be chosen (e.g. file) and events may be limited to the chosen ones only,
- Localizable - gives you functionality to convert units of measurement (e.g. kilometers to miles, etc.) or any other conversions desirable,
- Locatable - gives you functionality using the Google Maps API to automatically populate your model with latitude and longitide information using Google, a fantastic tool to use along with sfEasyGMapPlugin,
- Sortable - gives you sortable functionality to your models, enabling you to easily fetch next/previous objects, moving them up/down in a sorted list or swapping with another object,
- Taggable - adds Tagging capabilities, creates a TaggableTag table and a XxxTaggableTag table for each taggable model, using refClass m:n db table relation, provides easy tag management: add, remove, remove all, set, etc, finally, gives you the possibility to get the most popular tags (for a tag cloud, for example) fetched either from chosen models or from all of them,
plugin behaviors
Finally, there are also symfony plugins providing custom behaviors:
- sfDoctrineActAsSignablePlugin - a well developed alternative to blameable Doctrine extension,
- sfDoctrineActAsTaggablePlugin - provides tag management (alternative to taggable Doctrine extension), provides a tag cloud generation,
- csDoctrineActAsAttachablePlugin - associate various uploads with multiple models,
- sfDoctrineJCroppablePlugin - add user-croppable images to your models with a javascript image cropper,
- sfDoctrineNestedSetPlugin - a form and a validator providing easy NestedSet behavior management,
- csDoctrineActAsCategorizablePlugin - categorize your models, mix, match or separate multiple models into multiple nested/flat categories,
- sfDoctrineActAsRattablePlugin - rate Doctrine objects,
- vjCommentPlugin - provides commentable behavior to comment news page, articles, etc,
- ajDoctrineLuceneablePlugin - provides luceneable behavior with Lucene full text integration,
useful links about Doctrine behaviors:
- list of symfony behavior plugins,
- share properties between your models and one-to-one relationships,
- add default query parts that are automatically added to your queries when you reference the specified relationships,
- writing doctrine behavior,
- Diem behavior extensions,
- nesting behaviors,
http://symfony-world.blogspot.com/2010/10/symfonydoctrine-behavior-review.html
Assinar:
Postagens (Atom)