Uma vez que uma extensão visa ser utilizada por outros desenvolvedores, ela requer alguns esforços adicionais para ser criada. Estas são apenas algumas orientações gerais:
A seguir, descrevemos como criar uma nova extensão, de acordo com a sua categorização conforme descrita na visão geral. Estas descrições também se aplicam quando você está criando um componente usado principalmente em seus próprios projetos.
Um componente da aplicação deveria implementar a interface IApplicationComponent ou estender de CApplicationComponent. O método principal que precisa ser implementado é o IApplicationComponent::init no qual o componente faz algum trabalho de inicialização. Este método é invocado após cada componente ser criado e os valores de propriedades iniciais (especificados na configuração da aplicação) serem aplicados.
Por padrão, um componente de aplicação é criado e inicializado somente quando ele é acessado pela primeira vez durante o tratamento da requisição. Se um componente da aplicação precisa ser criado logo após a instância da aplicação ser criada, ele deveria exigir que o usuário listasse seu ID na propriedade CApplication::preload.
Para criar um comportamento, deve-se implementar a interface IBehavior. Por conveniência, o Yii fornece uma classe-mãe CBehavior que já implementa essa interface e fornece alguns métodos adicionais convenientes. As classes-filha na maioria dos casos só precisam implementar os métodos extra que elas pretendem tornar disponíveis aos componentes aos quais são anexadas.
Ao desenvolver comportamentos para CModel e CActiveRecord, pode-se também estender a CModelBehavior e a CActiveRecordBehavior, respectivamente. Essas classes-mãe oferecem recursos adicionais que foram criados especificamente para a CModel e a CActiveRecord. Por exemplo, a classe CActiveRecordBehavior implementa um grupo de métodos para responder aos eventos do ciclo de vida chamados em um objeto ActiveRecord. Desta forma, uma classe-filha pode sobrescrever estes métodos para inserir código personalizado que participará nos ciclos de vida do AR.
O código a seguir mostra um exemplo de um comportamento de ActiveRecord. Quando
este comportamento é anexado a um objeto AR e quando o objeto AR está sendo
salvo chamando o método save()
, ele automaticamente definirá os atributos
data_criacao
e data_atualizacao
com a timestamp atual.
class TimestampBehavior extends CActiveRecordBehavior
{
public function beforeSave($event)
{
if($this->owner->isNewRecord)
$this->owner->data_criacao=time();
else
$this->owner->data_atualizacao=time();
}
}
Um widget deve estender de CWidget ou suas classes-filha.
A maneira mais fácil de criar um novo widget é estender um widget existente e sobrescrer seus métodos ou alterar o valor padrão de suas propriedades. Por exemplo, se você quer usar um estilo CSS mais legal para a CTabView, você poderia configurar a sua propriedade CTabView::cssFile ao usar o widget. Você também pode estender a CTabView como segue de modo que você não precisa mais configurar a propriedade ao usar o widget.
class MyTabView extends CTabView
{
public function init()
{
if($this->cssFile===null)
{
$file=dirname(__FILE__).DIRECTORY_SEPARATOR.'tabview.css';
$this->cssFile=Yii::app()->getAssetManager()->publish($file);
}
parent::init();
}
}
No exemplo acima, sobrescrevemos o método CWidget::init e designamos para
CTabView::cssFile a URL que aponta para o nosso novo estilo CSS padrão, se a
propriedade não estiver definida. Colocamos o novo arquivo de estilo CSS sob o
mesmo diretório contendo o arquivo da classe MyTabView
de modo que eles possam
ser empacotados como uma extensão. Uma vez que o arquivo de estilo CSS não está
acessível na Web, precisamos publicá-lo como um asset.
Para criar um novo widget do zero, precisamos implementar principalmente dois
métodos: CWidget::init e CWidget::run. O primeiro método é chamado quando
usamos $this->beginWidget
para inserir um widget na visão, e o segundo método
é invocado quando chamamos $this->endWidget
. Se quisermos capturar e processar
o conteúdo exibido entre estas duas chamadas de métodos, podemos iniciar o
buffer de saída
em CWidget::init e obter a saída do buffer em CWidget::run para posterior
processamento.
Um widget frequentemente envolve incluir arquivos de CSS, JavaScript ou outros recursos na página que usa o widget. Chamamos esses arquivos de assets (posses, ativos) porque eles permanecem junto com o arquivo da classe do widget e geralmente não estão acessíveis aos usuários da Web. Para tornar estes arquivos acessíveis, precisamos publicá-los usando o CWebApplication::assetManager, conforme demonstrado no trecho de código acima. Além disso, se quiser incluir um arquivo CSS ou JavaScript na página atual, precisamos registrá-lo usando o CClientScript:
class MyWidget extends CWidget
{
protected function registerClientScript()
{
// ...publica o arquivo CSS ou JavaScript aqui...
$cs=Yii::app()->clientScript;
$cs->registerCssFile($cssFile);
$cs->registerScriptFile($jsFile);
}
}
Um widget também pode ter os seus próprios arquivos de visão. Se for o caso,
crie um diretório chamado views
dentro do diretório que contém o arquivo da
classe do widget, e coloque todos os arquivos de visão ali. Na classe do widget,
de modo a renderizar a visão do widget, use $this->render('ViewName')
, que
é parecido com o que fazemos num controle.
Uma ação deve herdar de CAction ou suas classes-filha. O método principal que precisa ser implementado para uma ação é o IAction::run.
Um filtro deve herdar de CFilter ou suas classes-filha. Os métodos principais que precisam ser implementados para um filtro são CFilter::preFilter e CFilter::postFilter. O primeiro é chamado antes da ação ser executada enquanto o outro é invocado depois.
class MyFilter extends CFilter
{
protected function preFilter($filterChain)
{
// lógica sendo aplicada antes que a ação seja executada
return true; // false se a ação não deveria ser executada
}
protected function postFilter($filterChain)
{
// lógica sendo aplicada após a ação ser executada
}
}
O parâmetro $filterChain
é do tipo CFilterChain, que contém informações
sobre a ação que está sendo filtrada.
Um controle distribuído como uma extensão deve
herdar de CExtController, ao invés de CController. O motivo principal é que
CController assume que os arquivos de visão do controle estão localizados em
application.views.ControllerID
, enquanto CExtController assume que os
arquivos de visão estão localizados sob o diretório views
que é um
subdiretório do diretório que contém o arquivo da classe do controle. Portanto,
é mais fácil redistribuir o controle, uma vez que seus arquivos de visão estão
juntos com o arquivo da classe do controle.
Um validador deve herdar de CValidator e implementar seu método CValidator::validateAttribute.
class MyValidator extends CValidator
{
protected function validateAttribute($model,$attribute)
{
$value=$model->$attribute;
if($value has error)
$model->addError($attribute,$errorMessage);
}
}
Um comando de console deve herdar de CConsoleCommand e implementar seu método CConsoleCommand::run. Opcionalmente, podemos sobrescrever CConsoleCommand::getHelp para disponibilizar alguma informação de ajuda amigável sobre o comando.
class MyCommand extends CConsoleCommand
{
public function run($args)
{
// $args dá um array dos argumentos de linha de comando deste comando
}
public function getHelp()
{
return 'Uso: como usar este comando';
}
}
Por favor, consulte a seção sobre módulos sobre como criar um módulo.
Uma regra geral para desenvolver um módulo é que ele deveria ser auto-contido. Arquivos de recursos (como CSS, JavaScript, imagens) que são usados por um módulo devem ser distribuídos junto com o módulo. E o módulo deve publicá-los de modo que eles estejam acessíveis na Web.
Desenvolver uma extensão de componente genérico é como escrever uma classe. Novamente, o componente também deve ser auto-contido para que ele possa ser facilmente usado por outros desenvolvedores.
Found a typo or you think this page needs improvement?
Edit it on github !
Signup or Login in order to comment.