All posts by tiX

Redirect para Referer (página anterior)

Esta técnica permite redireccionar o utilizador para a página anterior, no caso de existir, ou para a página principal:

public function executeShow(sfWebRequest $request)
{
// ....
$referer = $this->getRequest()->getReferer();
$this->redirect($referer ? $referer : '@homepage');
}

Espero que vos dê tanto jeito como a mim :)

Personalizar mensagens de erro nos formulários

Em symfony 1.4
No ficheiro ProjectConfiguration.class.php:
class FrontendConfiguration extends sfApplicationConfiguration {
public function configure()
{
sfValidatorBase::setDefaultMessage('required', 'This field is required.');
// etc etc
}

Em versões anteriores à 1.3


No ficheiro ProjectConfiguration.class.php:
class FrontendConfiguration extends sfApplicationConfiguration {
public function configure()
{
sfValidatorBase::setRequiredMessage("This field is required.");
sfValidatorBase::setInvalidMessage("This field is Invalid.");
// etc etc
}
}

Estranho Timestampable Behaviour..

Quando no schema.yml definimos o Timestampable Behaviour (ver este post), os campos created_at e updated_at aparecem no formulário desse objecto.
Como não queremos ter que preencher esses campos manualmente cada vez que estamos a editar ou adicionar algo, temos que fazer o unset dos mesmos na classe do formulário desse objecto.
Exemplo:
Em: lib/form/doctrine/CategoryFormClass.php
public function configure() {
unset($this->widgetSchema['created_at']);
unset($this->validatorSchema['created_at']);

unset($this->widgetSchema['updated_at']);
unset($this->validatorSchema['updated_at']);
}

É necessário fazer essa alteração em todas as classes de formulários…

Alternativamente pode-se alterar directamente o ficheiro lib/form/doctrine/BaseFormDoctrine.class.php que esses campos não apareçam em nenhum formulário.
public function setup(){
unset($this->widgetSchema['created_at']);
unset($this->validatorSchema['created_at']);

unset($this->widgetSchema['updated_at']);
unset($this->validatorSchema['updated_at']);
}

EDIT:
Para simplificar também se pode fazer o seguinte:

...
unset($this['created_at']);
unset($this['updated_at']);
...

Apagar ficheiros desnecessários do lib

Por vezes, enquanto estamos a acertar o modelo fazemos varias vezes build, e certamente que alguns ficheiros desnecessários vão ficar perdidos pelas paths lib/filter/, lib/model/ e lib/form/.

Como os únicos ficheiros que nos interessam são os que estão no schema.yml, com o seguinte comando podemos apagar de uma só vez todas as classes desnecessárias:

php symfony doctrine:clean

Exemplo:

[/sfdir/trunk]$ php symfony doctrine:clean --no-confirmation
>> file+ /private/var/tmp/doctrine_schema_18134.yml
>> doctrine Deleting "Article" files
>> file- /sfdir/trunk/lib/filter/doctrine/base/BaseArticleFormFilter.class.php
>> file- /sfdir/trunk/lib/filter/doctrine/ArticleFormFilter.class.php
>> file- /sfdir/trunk/lib/form/doctrine/base/BaseArticleForm.class.php
>> file- /sfdir/trunk/lib/form/doctrine/ArticleForm.class.php
>> file- /sfdir/trunk/lib/model/doctrine/base/BaseArticle.class.php
>> file- /sfdir/trunk/lib/model/doctrine/ArticleTable.class.php
>> file- /sfdir/trunk/lib/model/doctrine/Article.class.php
>> doctrine Deleting "Category" files
...

Caso pretendam limpar TODAS as classes do projecto, limpem o ficheiro schema.yml e corram o comando acima.

Definições gerais de tabelas, relacionamentos automáticos e Behaviors

Definir Collation e Charset para todas as tabelas

Há determinadas definições de classes/tabelas que por vezes queremos generalizar. Uma delas é, concerteza, a collation e o charset das tabelas.

Para não termos que repetir todas essas definições em cada tabela basta colocar o seguinte no topo do ficheiro config/doctrine/schema.yml:

options:
collate: utf8_unicode_ci
charset: utf8


Relacionamentos automáticos entre tabelas
(Apenas para tabelas do tipo InnoDB)

Com Doctrine, é possivel relacionar automaticamente tabelas uma vez que através dos nomes das colunas é detectado se existe tabela associada a esse nome.

Para tal, basta definir o seguinte atributo no topo do ficheiro config/doctrine/schema.yml:

detect_relations: true

No exemplo seguinte, a tabela Entity relaciona com a tabela Category através do campo category_id:

Category:
columns:
id: { type: integer(4), primary: true, autoincrement: true }
name: { type: string(255), notnull: true }

Entity:
columns:
id: { type: integer(4), primary: true, autoincrement: true }
name: { type: string(255), notnull: true }
category_id: { type: integer(4) }

Como o campo category_id tem o mesmo nome da tabela Category, o relacionamento é automaticamente detectado.

Para ler mais sobre sintax abreviada em Doctrine sigam este link:
http://www.doctrine-project.org/documentation/manual/1_2/en/yaml-schema-files#abbreviated-syntax


Behaviors

Timestampable - gera automaticamente campos created_at e updated_at

Estes campos também são gerados automaticamente utilizando o atributo Timestampable na definição da classe. Assim, para gerarmos esses campos para a tabela Category:

Category:
actAs: { Timestampable: ~ }
columns:
...

Sluggable – gera automaticamete campo slug

Com este behavior o campo slug é gerado automaticamente para um ou vários campos duma tabela. Quando o objecto é guardado, a respectiva slug user friendly é criada:

Glossary:
actAs:
Sluggable:
unique: true
fields: [word]
canUpdate: true
columns:
word: { type: string(255), notnull: true, unique: true }
...

Mais sobre behaviors:
http://www.doctrine-project.org/documentation/manual/1_2/en/behaviors

Definir tipo Enum com Doctrine

Utilizando o Doctrine podemos definir facilmente o tipo Enum para qualquer classe.

Para que tal seja possível temos que acrescentar o atributo use_native_enum no nosso ficheiro de configuração da base de dados em config/databases.yml:

all:
doctrine:
class: sfDoctrineDatabase
param:
dsn: 'mysql:host=localhost;dbname=symfony12doctrine'
username: user
attributes:
use_native_enum: true

Agora, no ficheiro config/doctrine/schema.yml:

Contact:
columns:
id: { type: integer(4), primary: true, autoincrement: true }
name: { type: string(255) }
gender:
type: enum
values: ['M','F']
default: M

E o resultado em SQL será algo do género:

CREATE TABLE `contact` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`gender` enum('M','F') COLLATE utf8_unicode_ci DEFAULT 'M',
PRIMARY KEY (`id`)
) ENGINE=InnoDB

Para mais informações sobre os data types suportados pelo Doctrine/Sql sigam este link:

http://www.symfony-project.org/doctrine/1_2/en/04-Schema-Files

Imagens, css e javascripts de um novo projecto.

Depois de iniciar-mos um projeto no symfony pelo comando init-project o directório web/ não tem as imagens, css e javascripts que possivelmente vamos precisar.

Todos esses ficheiros estão na sandbox, por isso guardei todos os ficheiros da sandbox num directório e criei o seguinte script para automaticamente copiar todos os ficheiros necessários:

1
#!/bin/bash       <br />STR="/Applications/XAMPP/xamppfiles/bin/sf_sandbox/web"<br />TO="${PWD}/web"<br /><br />echo "* Copying css, js and image files from sandbox to working directory..."<br />echo<br /><br />#### css<br />CSS_FROM="${STR}/css/main.css"<br />CSS_TO="${TO}/css/"<br />echo "> ${CSS_FROM} ==> ${CSS_TO}"<br />cp $CSS_FROM $CSS_TO<br />echo "* Copied 'main.css'"<br /><br />#### sf<br />SF_FROM="${STR}/sf/"<br />SF_TO="${TO}/sf/"<br />echo "> ${SF_FROM} ==> ${SF_TO}"<br />echo "* 'sf' directory created at ${SF_TO}"<br />cp -R $SF_FROM $SF_TO<br /><br />#### js<br />JS_FROM="/Applications/XAMPP/xamppfiles/bin/sf_sandbox/lib/symfony/plugins/sfProtoculousPlugin/web/js/prototype.js"<br />JS_TO="${SF_TO}js/"<br />mkdir -p "${JS_TO}"<br />echo "> ${JS_FROM} ==> ${JS_TO}"<br />cp $JS_FROM $JS_TO<br />echo "* Copied 'prototype.js'"<br /><br />echo<br />echo "* All done."

Alterem as variáveis STR e JS_FROM para os vossos directórios e guardem o script com o nome sfsandboximgs e com permissão de execução (chmod +x sfsandboximgs).

Agora, é mais fácil criar um projecto symfony com todos os ficheiros necessários no directório web:

1
symfony init-project <<span style="font-style: italic;">nome_do_projecto></span><br />./sfsandboximgs

Utilizar diferentes separadores de segmentos nos routings

Por defeito os separadores de segmentos de routing no symfony são: ‘/‘ e ‘.

Para utilizar um conjunto mais alargado de caracteres separadores de segmentos basta:

Editar o ficheiro: apps/app/config/factories.yml

all:
routing:
class: sfPatternRouting
param:
generate_shortest_url: true
extra_parameters_as_query_string: true
segment_separators: [/, ., -]

Neste exemplo, foi adicionado o separador “-“.

É agora possivel criar routings do género:

course:
url: /formacao/cursos-:sub_category/:entity/curso-:course/:id