forked from yiisoft/yii2
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' of git://github.com/yiisoft/yii2 into guide-str…
…ucture-controllers
- Loading branch information
Showing
84 changed files
with
6,875 additions
and
277 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,246 @@ | ||
Eventos | ||
======= | ||
Eventos permitem que você injete código personalizado dentro de outo código existente em determinados pontos de execução. Você pode anexar o código personalizado a um evento de modo que quando o evento é acionado, o código é executado automaticamente. Por exemplo, um objeto de e-mail pode disparar um evento `messageSent` quando o envio da mensagem for bem sucedida. Se você quiser acompanhar as mensagens que são enviadas com sucesso, você poderia então simplesmente anexar o código de acompanhamento ao evento `messageSent`. | ||
Yii disponibiliza uma classe base chamada [[yii\base\Component]] para dar suporte a eventos. | ||
Se sua classe precisar disparar eventos, ela deverá estender de [[yii\base\Component]], ou de uma classe-filha. | ||
|
||
Manipuladores de Evento <span id="event-handlers"></span> | ||
-------------- | ||
|
||
Um manipulador de evento é uma função [Callback do PHP] (http://www.php.net/manual/en/language.types.callable.php) que é executada quando o evento é disparado. Você pode usar qualquer um dos seguintes callbacks: | ||
- uma função global do PHP especificada como uma string (sem parênteses), por exemplo, `'trim'`; | ||
- Um método do objeto especificado como um array, informando o objeto e um nome do método como uma string (sem parênteses), por exemplo `[$object, 'methodName']`; | ||
- Um método estático da classe especificado como um array informando o nome da classe e nome do método como string (sem parênteses), por exemplo, `['ClassName', 'methodName']`; | ||
- Uma função anônima, por exemplo, `function ($event) { ... }`. | ||
|
||
A assinatura de um manipulador de eventos é: | ||
|
||
```php | ||
function ($event) { | ||
// $event is an object of yii\base\Event or a child class | ||
} | ||
``` | ||
|
||
Através do parâmetro `$event`, um manipulador de evento pode receber as seguintes informações sobre o evento que ocorreu: | ||
|
||
- [[yii\base\Event::name|event name]] | ||
- [[yii\base\Event::sender|event sender]]: o objeto cujo método `trigger()` foi chamado | ||
- [[yii\base\Event::data|custom data]]: os dados que são fornecidos ao anexar o manipulador de eventos (a ser explicado a seguir) | ||
|
||
|
||
Anexando manipuladores de eventos <span id="attaching-event-handlers"></span> | ||
------------------------ | ||
|
||
Você pode anexar um manipulador para um evento, chamando o método [[yii\base\Component::on()]]. Por exemplo: | ||
|
||
```php | ||
$foo = new Foo; | ||
|
||
// esse manipulador é uma função global | ||
$foo->on(Foo::EVENT_HELLO, 'function_name'); | ||
|
||
// esse manipulador é um método de objeto | ||
$foo->on(Foo::EVENT_HELLO, [$object, 'methodName']); | ||
|
||
// esse manipulador é um método estático da classe | ||
$foo->on(Foo::EVENT_HELLO, ['app\components\Bar', 'methodName']); | ||
|
||
// esse manipulador é uma função anônima | ||
$foo->on(Foo::EVENT_HELLO, function ($event) { | ||
// Código ... | ||
}); | ||
``` | ||
|
||
Você também pode anexar manipuladores de eventos por meio de [configurações](concept-configurations.md). Para mais detalhes, consulte a seção [Configurações](concept-configurations.md#configuration-format). | ||
|
||
Ao anexar um manipulador de eventos, você pode fornecer dados adicionais no terceiro parâmetro do método [[yii\base\Component::on()]]. | ||
Os dados serão disponibilizados para o manipulador quando o evento for disparado e o manipulador chamado. Por exemplo: | ||
|
||
```php | ||
// O código a seguir mostrará "abc" quando o evento for disparado | ||
// porque $event->data contêm os dados passados no terceiro parâmetro do "on" | ||
$foo->on(Foo::EVENT_HELLO, 'function_name', 'abc'); | ||
|
||
function function_name($event) { | ||
echo $event->data; | ||
} | ||
``` | ||
|
||
Ordem dos Manipuladores de Eventos | ||
------------------- | ||
|
||
Você pode anexar um ou mais manipuladores para um único evento. Quando o evento é disparado, os manipuladores anexados serão chamados na ordem em que eles foram anexados ao evento. Se o manipulador precisar interromper os eventos subsequentes, pode definir a propriedade [[yii\base\Event::handled]] do parâmetro `$event` para *true*: | ||
|
||
```php | ||
$foo->on(Foo::EVENT_HELLO, function ($event) { | ||
$event->handled = true; | ||
}); | ||
``` | ||
|
||
Por padrão, um novo manipulador é anexado a fila de manipuladores existente para o evento. | ||
|
||
Como resultado, o manipulador será chamado por último quando o evento for disparado. | ||
|
||
Para inserir um novo manipulador de evento no início da fila de modo a ser chamado primeiro, você pode chamar o método [[yii\base\Component::on()]], passando *false* para o quarto parâmetro `$append`: | ||
|
||
```php | ||
$foo->on(Foo::EVENT_HELLO, function ($event) { | ||
// ... | ||
}, $data, false); | ||
``` | ||
|
||
Disparando Eventos <span id="triggering-events"></span> | ||
----------------- | ||
|
||
Os eventos são disparados chamando o método [[yii\base\Component::trigger()]]. Este método requer um *nome de evento*, e, opcionalmente, um objeto de evento que descreve os parâmetros a serem passados para os manipuladores de eventos. Por exemplo: | ||
|
||
```php | ||
namespace app\components; | ||
|
||
use yii\base\Component; | ||
use yii\base\Event; | ||
|
||
class Foo extends Component | ||
{ | ||
const EVENT_HELLO = 'hello'; | ||
|
||
public function bar() | ||
{ | ||
$this->trigger(self::EVENT_HELLO); | ||
} | ||
} | ||
``` | ||
|
||
Com o código acima, todas as chamadas para `bar ()` irão disparar um evento chamado `hello`. | ||
|
||
> Dica: Recomenda-se usar constantes de classe para representar nomes de eventos. No exemplo acima, a constante `EVENT_HELLO` representa o evento `hello`. Esta abordagem tem três benefícios. Primeiro, previne erros de digitação. Segundo, pode fazer o evento se tornar reconhecível para recursos de *auto-complete* de IDEs. Terceiro, você pode especificar quais eventos são suportados em uma classe, basta verificar suas declarações de constantes. | ||
Às vezes, quando um evento é disparado você pode querer passar junto informações adicionais para os manipuladores de eventos. Por exemplo, um objeto de e-mail pode querer passar uma informação para o manipulador do evento `messageSent` de modo que os manipuladores podem conhecer os detalhes das mensagens enviadas. Para fazer isso, você pode fornecer um objeto de evento como o segundo parâmetro para o método [[yii\base\Component::trigger()]]. Este objeto precisa ser uma instância da classe [[yii\base\Event]] ou de uma classe filha. Por exemplo: | ||
|
||
```php | ||
namespace app\components; | ||
|
||
use yii\base\Component; | ||
use yii\base\Event; | ||
|
||
class MessageEvent extends Event | ||
{ | ||
public $message; | ||
} | ||
|
||
class Mailer extends Component | ||
{ | ||
const EVENT_MESSAGE_SENT = 'messageSent'; | ||
|
||
public function send($message) | ||
{ | ||
// ...sending $message... | ||
|
||
$event = new MessageEvent; | ||
$event->message = $message; | ||
$this->trigger(self::EVENT_MESSAGE_SENT, $event); | ||
} | ||
} | ||
``` | ||
|
||
Quando o método [[yii\base\Component::trigger()]] é chamado, ele chamará todos os manipuladores ligados ao evento passado. | ||
|
||
Desvinculando manipuladores de eventos <span id="detaching-event-handlers"></span> | ||
------------------------ | ||
|
||
Para retirar um manipulador de um evento, chame o método [[yii\base\Component::off()]]. Por Exemplo: | ||
|
||
```php | ||
// o manipulador é uma função global | ||
$foo->off(Foo::EVENT_HELLO, 'function_name'); | ||
|
||
// o manipulador é um método de objeto | ||
$foo->off(Foo::EVENT_HELLO, [$object, 'methodName']); | ||
|
||
// o manipulador é um método de estático da Classe | ||
$foo->off(Foo::EVENT_HELLO, ['app\components\Bar', 'methodName']); | ||
|
||
// o manipulador é uma função anônima | ||
$foo->off(Foo::EVENT_HELLO, $anonymousFunction); | ||
``` | ||
|
||
Note que, em geral, você não deve tentar desvincular uma função anônima, a menos que você guarde em algum lugar quando ela for ligada ao evento. No exemplo acima, é assumido que a função anónima é armazenada em uma variável `$anonymousFunction`. | ||
|
||
Para desvincular todos os manipuladores de um evento, simplesmente chame [[yii\base\Component::off()]] sem o segundo parâmetro: | ||
|
||
```php | ||
$foo->off(Foo::EVENT_HELLO); | ||
``` | ||
|
||
|
||
Manipuladores de Eventos de Classe <span id="class-level-event-handlers"></span> | ||
-------------------------- | ||
|
||
As subseções acima descreveram como anexar um manipulador para um evento a *nível de instância* (objeto). | ||
Às vezes, você pode querer responder a um evento acionado por *todas* as instâncias da classe em vez de apenas uma instânica específica. Em vez de anexar um manipulador de evento em todas as instâncias, você pode anexar o manipulador a *nível da classe* chamando o método estático [[yii\base\Event::on()]]. | ||
|
||
Por Exemplo, um objeto [Active Record](db-active-record.md) irá disparar um evento [[yii\db\BaseActiveRecord::EVENT_AFTER_INSERT|EVENT_AFTER_INSERT]] sempre que inserir um novo registro no database. A fim de acompanhar inserções feitas por *cada* objeto | ||
[Active Record](db-active-record.md), você pode usar o seguinte código: | ||
|
||
```php | ||
use Yii; | ||
use yii\base\Event; | ||
use yii\db\ActiveRecord; | ||
|
||
Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) { | ||
Yii::trace(get_class($event->sender) . ' is inserted'); | ||
}); | ||
``` | ||
|
||
O manipulador de evento será invocado sempre que uma instância de [[yii\db\ActiveRecord|ActiveRecord]], ou uma de suas classes filhas, disparar o evento [[yii\db\BaseActiveRecord::EVENT_AFTER_INSERT|EVENT_AFTER_INSERT]]. No manipulador, você pode obter o objeto que disparou o evento através de `$event->sender`. | ||
|
||
Quando um objecto dispara um evento, ele irá primeiro chamar manipuladores de nível de instância, seguido pelos manipuladores de nível de classe. | ||
|
||
Você pode disparar um evento de *nível de classe* chamando o método estático [[yii\base\Event::trigger()]]. Um evento de nível de classe não está associado com um objeto particular. Como resultado, ele fará a chamada dos manipuladores de eventos apenas a nível da classe. Por exemplo: | ||
|
||
```php | ||
use yii\base\Event; | ||
|
||
Event::on(Foo::className(), Foo::EVENT_HELLO, function ($event) { | ||
echo $event->sender; // displays "app\models\Foo" | ||
}); | ||
|
||
Event::trigger(Foo::className(), Foo::EVENT_HELLO); | ||
``` | ||
|
||
Note que, neste caso, `$event->sender` refere-se ao nome da classe acionando o evento em vez de uma instância do objeto. | ||
|
||
> Nota: Porque um manipulador de nível de classe vai responder a um evento acionado por qualquer instância dessa classe, ou qualquer classe filha, você deve usá-lo com cuidado, especialmente se a classe é uma classe base de baixo nível, tal como [[yii\base\Object]]. | ||
Para desvincular um manipulador de evento de nível de classe, chame [[yii\base\Event::off()]]. Por Exemplo: | ||
|
||
```php | ||
// desvincula $handler | ||
Event::off(Foo::className(), Foo::EVENT_HELLO, $handler); | ||
|
||
// Desvincula todos os manipuladores de Foo::EVENT_HELLO | ||
Event::off(Foo::className(), Foo::EVENT_HELLO); | ||
``` | ||
|
||
|
||
Eventos Globais <span id="global-events"></span> | ||
------------- | ||
|
||
Yii suporta o assim chamado *evento global*, que na verdade é um truque com base no mecanismo de eventos acima descrito. | ||
O evento global requer um *singleton* acessível globalmente, tal como a própria instância [application](structure-applications.md). | ||
|
||
Para criar o evento global, um evento *remetente* chama o método singleton `trigger()` para disparar o evento, em vez de chamar o método `trigger()` do *remetente* . Da mesma forma, os manipuladores de eventos são anexados ao evento no *singleton* . Por exemplo: | ||
|
||
```php | ||
use Yii; | ||
use yii\base\Event; | ||
use app\components\Foo; | ||
|
||
Yii::$app->on('bar', function ($event) { | ||
echo get_class($event->sender); // Mostra na tela "app\components\Foo" | ||
}); | ||
|
||
Yii::$app->trigger('bar', new Event(['sender' => new Foo])); | ||
``` | ||
A vantagem de usar eventos globais é que você não precisa de um objeto ao anexar um manipulador para o evento que será acionado pelo objeto. Em vez disso, a inclusão do manipulador e o evento acionado são ambos feitos através do *singleton*. (Por exemplo uma instância de application). | ||
Contudo, porque o namespace dos eventos globais é compartilhado com todos, você deve nomear os eventos globais sabiamente, tais como a introdução de algum tipo de namespace (por exemplo. "frontend.mail.sent", "backend.mail.sent"). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
Propriedades | ||
=========== | ||
|
||
No PHP, atributos da classe são sempre chamadas de *propriedades*. Esses atributos fazem parte da definição da classe e são usadas para representar o estado de uma instância da classe (para diferenciar uma instância da classe de outra). Na prática, muitas vezes você pode querer lidar com a leitura ou a escrita de propriedades de maneiras especiais. Por Exemplo, você pode querer trimar uma string sempre que for atribuído um valor para a propriedade `label`. Você *poderia* usar o código a seguir para realizar esta tarefa: | ||
|
||
```php | ||
$object->label = trim($label); | ||
``` | ||
|
||
A desvantagem do código acima é que você teria que chamar `trim ()` em todos os lugares onde você definir a propriedade `label` no seu código. Se, no futuro, a propriedade `label` receber um novo requisito, tais como a primeira letra deve ser capitalizado, você teria que modificar novamente todos os pedaços de código que atribui um valor para a propriedade `label`. A repetição de código leva a erros, e é uma prática que você deve evitar sempre que possível. | ||
|
||
Para resolver este problema, Yii introduz uma classe base chamada [[yii\base\Object]] que suporta definições de propriedades baseadas nos métodos *getter* e *setter* da classe. Se uma classe precisa dessa funcionalidade, ela deve estender de [[yii\base\Object]], ou de uma classe-filha. | ||
|
||
> Informação: Quase todas as classes nativas (core) do framework Yii estendem de [[yii\base\Object]] ou de uma classe-filha. Isto significa que sempre que você vê um método *getter* ou *setter* em uma classe nativa (core), você pode usá-lo como uma propriedade. | ||
Um método getter é um método cujo nome inicia com a palavra `get`; um método setter inicia com `set`. | ||
O nome depois do prefixo `get` ou `set` define o nome da propriedade. Por exemplo, um getter `getLabel()` e/ou um setter `setLabel()` define a propriedade chamada `label`, como mostrado no código a seguir: | ||
|
||
```php | ||
namespace app\components; | ||
|
||
use yii\base\Object; | ||
|
||
class Foo extends Object | ||
{ | ||
private $_label; | ||
|
||
public function getLabel() | ||
{ | ||
return $this->_label; | ||
} | ||
|
||
public function setLabel($value) | ||
{ | ||
$this->_label = trim($value); | ||
} | ||
} | ||
``` | ||
|
||
(Para ser claro, os métodos getter e setter criam a propriedade `label`, que neste caso internamente refere-se ao atributo privado chamado `_label`.) | ||
|
||
Propriedades definidas por getters e setters podem ser usados como atributos da classe. A principal diferença é que quando tal propriedade é iniciada para leitura, O método getter correspondente será chamado; quando a propriedade é iniciada atribuindo um valor, o método setter correspondente será chamado. Por Exemplo: | ||
|
||
```php | ||
// equivalent to $label = $object->getLabel(); | ||
$label = $object->label; | ||
|
||
// equivalent to $object->setLabel('abc'); | ||
$object->label = 'abc'; | ||
``` | ||
|
||
A propriedade definida por um método getter sem um método setter é *somente de leitura*. Tentando atribuir um valor a tal propriedade causará uma exceção [[yii\base\InvalidCallException|InvalidCallException]]. Semelhantemente, uma propriedade definida por um método setter sem um método getter é *somente de gravação *, e tentar ler tal propriedade também causará uma exceção. Não é comum ter propriedade *somente de gravação*. | ||
|
||
Existem várias regras especiais para, e limitações sobre, as propriedades definidas via getters e setters: | ||
|
||
* Os nomes dessas propriedades são *case-insensitive*. Por exemplo, `$object->label` e `$object->Label` são a mesma coisa. Isso ocorre porque nomes de métodos no PHP são case-insensitive. | ||
* Se o nome de uma tal propriedade é o mesmo que um atributo da classe, esta última terá precedência. Por exemplo, se a classe `Foo` descrita acima tiver um atributo `label`, então a atribuição `$object->label = 'abc'` afetará o *atributo* 'label'; esta linha não executaria `setLabel()` método setter. | ||
* Essas propriedades não suportam visibilidade. Não faz nenhuma diferença para a definição dos métodos getter ou setter se a propriedade é pública, protegida ou privada. | ||
* As propriedades somente podem ser definidas por getters e/ou setters *não estáticos*. Os métodos estáticos não serão tratados da mesma maneira. | ||
|
||
Voltando para o problema descrito no início deste guia, em vez de chamar `trim()` em todos os lugares que um valor for atribuído a `label`, `trim()`Agora, só precisa ser invocado dentro do setter `setLabel()`.E se uma nova exigência faz com que seja necessário que o 'label' seja inicializado capitalizado, o método `setLabel()` pode rapidamente ser modificado sem tocar em nenhum outro código. Esta única mudança afetará de forma global cada atribuição à propriedade `label`. |
Oops, something went wrong.