John Was
9 years ago
353 changed files with 17816 additions and 1725 deletions
@ -0,0 +1,356 @@
|
||||
Cache de Dados |
||||
============ |
||||
|
||||
O Cache de Dados é responsável por armazenar uma ou mais variáveis PHP em um arquivo temporário para |
||||
ser recuperado posteriormente. |
||||
Este também é a fundação para funcionalidades mais avançadas do cache, como [cache de consulta](#query-caching) |
||||
e [cache de página](caching-page.md). |
||||
|
||||
O código a seguir é um padrão de uso típico de cache de dados, onde `$cache` refere-se a |
||||
um [Componente de Cache](#cache-components): |
||||
|
||||
```php |
||||
// tentar recuperar $data do cache |
||||
$data = $cache->get($key); |
||||
|
||||
if ($data === false) { |
||||
|
||||
// $data não foi encontrado no cache, calculá-la do zero |
||||
|
||||
// armzaenar $data no cache para que esta possa ser recuperada na próxima vez |
||||
$cache->set($key, $data); |
||||
} |
||||
|
||||
// $data é acessível a partir daqui |
||||
``` |
||||
|
||||
|
||||
## Componentes de Cache <span id="cache-components"></span> |
||||
|
||||
O cache de dados se baseia nos, então chamados, *Componentes de Cache* que representam vários armazenamentos de cache, |
||||
como memória, arquivos, bancos de dados. |
||||
|
||||
Componentes de Cache são normalmente registrados como [componentes de aplicação](structure-application-components.md) para que possam ser globalmente configuraveis e acessiveis. O código a seguir exibe como configurar o componente de aplicação `cache` para usar [memcached](http://memcached.org/) com dois servidores de cache: |
||||
|
||||
```php |
||||
'components' => [ |
||||
'cache' => [ |
||||
'class' => 'yii\caching\MemCache', |
||||
'servers' => [ |
||||
[ |
||||
'host' => 'servidor1', |
||||
'port' => 11211, |
||||
'weight' => 100, |
||||
], |
||||
[ |
||||
'host' => 'servidor2', |
||||
'port' => 11211, |
||||
'weight' => 50, |
||||
], |
||||
], |
||||
], |
||||
], |
||||
``` |
||||
|
||||
Você pode então, acessar o componente de cache acima usando a expressão `Yii::$app->cache`. |
||||
|
||||
Já que todos os componentes de cache suportam as mesmas APIs, você pode trocar o componente de cache por outro |
||||
reconfigurando-o nas configurações da aplicação sem modificar o código que usa o cache. |
||||
Por exemplo, você pode modificar a configuração acima para usar [[yii\caching\ApcCache|APC cache]]: |
||||
|
||||
|
||||
```php |
||||
'components' => [ |
||||
'cache' => [ |
||||
'class' => 'yii\caching\ApcCache', |
||||
], |
||||
], |
||||
``` |
||||
|
||||
> Dica: você pode registrar múltiplos componentes de cache na aplicação. O componente chamado `cache` é usado |
||||
por padrão por muitas classes dependentes de cache (ex. [[yii\web\UrlManager]]). |
||||
|
||||
|
||||
### Sistemas de cache suportados <span id="supported-cache-storage"></span> |
||||
|
||||
Yii suporta uma ampla gama de sistemas de cache. A seguir um sumario: |
||||
|
||||
* [[yii\caching\ApcCache]]: usa a extensão do PHP [APC](http://php.net/manual/en/book.apc.php). Esta opção pode ser |
||||
considerada a mais rápida ao se implementar o cache de uma aplicação densa e centralizada (ex. um |
||||
servidor, sem balanceadores de carga dedicados, etc.). |
||||
* [[yii\caching\DbCache]]: usa uma tabela no banco de dados para armazenar os dados em cache. Para usar este cache |
||||
você deve criar uma tabela como especificada em [[yii\caching\DbCache::cacheTable]]. |
||||
* [[yii\caching\DummyCache]]: serve apenas como um substituto e não faz nenhum cache na realidade |
||||
O propósito deste comoponente é simplificar o codigo que precisa checar se o cache está disponível. |
||||
Por exemplo, durante o desenvolvimento or se o servidor não suporta cache, você pode configurar um |
||||
componente de cache para usar este cache. Quando o suporte ao cache for habilitado, você pode trocar o |
||||
para o componente correspondente. Em ambos os casos, você pode usar o mesmo código |
||||
`Yii::$app->cache->get($key)` para tentar recuperar os dados do cache sem se procupar que |
||||
`Yii::$app->cache` possa ser `null`. |
||||
* [[yii\caching\FileCache]]: usa arquivos para armazenar os dados em cache. Este é particularmente indicado |
||||
para armazenar grandes quantidades de dados como o conteúdo da página. |
||||
* [[yii\caching\MemCache]]: usa o [memcache](http://php.net/manual/en/book.memcache.php) do PHP e as extensões |
||||
[memcached](http://php.net/manual/en/book.memcached.php). Esta opção pode ser considerada a mais rápida |
||||
ao se implementar o cache em aplicações distribuidas (ex. vários servidores, balanceadores de carga, etc.) |
||||
* [[yii\redis\Cache]]: implementa um componente de cache baseado em armazenamento chave-valor |
||||
[Redis](http://redis.io/) (requere redis versão 2.6.12 ou mais recente). |
||||
* [[yii\caching\WinCache]]: usa a extensão PHP [WinCache](http://iis.net/downloads/microsoft/wincache-extension) |
||||
([veja também](http://php.net/manual/en/book.wincache.php)). |
||||
* [[yii\caching\XCache]]: usa a extensão PHP [XCache](http://xcache.lighttpd.net/). |
||||
* [[yii\caching\ZendDataCache]]: usa |
||||
[Cache de Dados Zend](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm) |
||||
como o meio de cache subjacente. |
||||
|
||||
|
||||
> Dica: Você pode usar vários tipos de cache na mesma aplicação. Uma estratégia comum é usar caches baseados |
||||
em memória para armazenar dados pequenos mas constantemente usados (ex. dados estatísticos), e usar caches |
||||
baseados em arquivo ou banco da dados para armazenar dados que são maiores mas são menos usados |
||||
(ex. conteúdo da página). |
||||
|
||||
|
||||
## APIs De Cache <span id="cache-apis"></span> |
||||
|
||||
Todos os componentes de caches extendem a mesma classe base [[yii\caching\Cache]] e assim suportam as seguintes APIs: |
||||
|
||||
* [[yii\caching\Cache::get()|get()]]: recupera um registro no cache usando uma chave específica. |
||||
Retorna `false` caso o item não for encontrado no cache ou se o registro está expirado/invalidado. |
||||
* [[yii\caching\Cache::set()|set()]]: armazena um registro no cache identificado por uma chave. |
||||
* [[yii\caching\Cache::add()|add()]]: armazena um registro no cache identificado por uma chave se a chave não |
||||
for encontrada em cache. |
||||
* [[yii\caching\Cache::mget()|mget()]]: recupera múltiplos registros do cache com as chaves especificadas. |
||||
* [[yii\caching\Cache::mset()|mset()]]: armazena múltiplos registros no cachee. Cada item identificado por uma chave. |
||||
* [[yii\caching\Cache::madd()|madd()]]: armazena múltiplos registros no cachee. Cada item identificado por uma chave. |
||||
Se a chave já existir em cache, o registro é ignorado. |
||||
* [[yii\caching\Cache::exists()|exists()]]: retorna se a chave específica é encontrada no cache. |
||||
* [[yii\caching\Cache::delete()|delete()]]: remove um registro do cache identificado por uma chave. |
||||
* [[yii\caching\Cache::flush()|flush()]]: remove todos os registros do cache. |
||||
|
||||
> Note: Não armazene o valor boleano `false` diretamente, porque o método [[yii\caching\Cache::get()|get()]] retorna `false`para indicar que o registro não foi encontrado em cache. Você pode armazena `false` em um array e armazenar este em cache para evitar este problema. |
||||
|
||||
Alguns tipos de cache como MemCache, APC, suportam recuperar em lote múltiplos registros em cache, o que poder reduzir |
||||
o custo de processamento envolvido ao recuperar informações em cache. The APIs [[yii\caching\Cache::mget()|mget()]] |
||||
e [[yii\caching\Cache::madd()|madd()]] são equipadas para explorar esta funcionalidade. Em caso do cache em questão não suportar esta funcionalidade, ele será simulado. |
||||
|
||||
Como [[yii\caching\Cache]] implementa `ArrayAccess`, um componente de cache pode ser usado como um array. A seguir alguns exemplos: |
||||
|
||||
```php |
||||
$cache['var1'] = $valor1; // equivalente a: $cache->set('var1', $valor1); |
||||
$valor2 = $cache['var2']; // equivalente a: $valor2 = $cache->get('var2'); |
||||
``` |
||||
|
||||
|
||||
### Chaves de Cache <span id="cache-keys"></span> |
||||
|
||||
Cada registro armazenado no cache é identificado por uma chave única. Quando você armazena um registro em cache, |
||||
você deve especificar uma chave para ele. Mais tarde, quando você quiser recuperar o registro do cache, você deve |
||||
fornecer a chave correspondente. |
||||
|
||||
Você pode usar uma string ou um valor arbitrario como uma chave do cache. Quando a chave não for uma string, ela será |
||||
automaticamente serializada em uma string. |
||||
|
||||
Uma estratégia comum ao definir uma chave de cache é incluir todos os fatores determinantes na forma de um array. |
||||
Por exemplo, [[yii\db\Schema]] usa a seguinte chave para armazenar a informação de um esquema de uma tabela do banco |
||||
de dados. |
||||
|
||||
```php |
||||
[ |
||||
__CLASS__, // nome da classe do esquema |
||||
$this->db->dsn, // nome da fonte de dados da conexão BD |
||||
$this->db->username, // usuario da conexão BD |
||||
$name, // nome da tabela |
||||
]; |
||||
``` |
||||
|
||||
Como você pode ver, a chave inclui toda a informação necessária para especificar unicamente uma tabela do banco. |
||||
|
||||
Quando o cache de diferentes aplicações é armazenado no mesmo lugar, é aconselhavel especificar, para cada |
||||
aplicação, um prefíxo único a chave do cache para evitar conflitos entre elas. Isto pode ser feito ao configurar |
||||
a propriedade [[yii\caching\Cache::keyPrefix]]. Por exemplo, na configuração da aplicação você pode escrever o seguinte código: |
||||
|
||||
```php |
||||
'components' => [ |
||||
'cache' => [ |
||||
'class' => 'yii\caching\ApcCache', |
||||
'keyPrefix' => 'minhaapp', // um prefíxo de chave único |
||||
], |
||||
], |
||||
``` |
||||
Para assegurar interoperabilidade, apenas caracteres numéricos devem ser usados. |
||||
To ensure interoperability, only alphanumeric characters should be used. |
||||
|
||||
|
||||
### Expiração de Cache <span id="cache-expiration"></span> |
||||
|
||||
Um registro armazenado em cache não será apagado a menos que seja removido por alguma política seja aplicada |
||||
(ex. espaço determinado para o cache esteja cheio e os registros mais antigos sejam removidos). Para alterar |
||||
estes comportamente, você pode fornecer um parametro de expiração ao chamar [[yii\caching\Cache::set()|set()]] |
||||
para armazenar um registro. O parametro indica por quantos segundos um registro pode permanecer válidado no cache. |
||||
Quando você chamar [[yii\caching\Cache::get()|get()]] para recuperar um registro, se o tempo de expiração houver passado, o método irá retornar `false`, indicando que o registro não foi encontrado no cache. Por exemplo, |
||||
|
||||
```php |
||||
// Manter o registro em cache por até 45 segundos |
||||
$cache->set($chave, $registro, 45); |
||||
|
||||
sleep(50); |
||||
|
||||
$data = $cache->get($chave); |
||||
if ($registro === false) { |
||||
// $registro está expirado ou não foi encontrado no sistema |
||||
} |
||||
``` |
||||
|
||||
|
||||
### Dependências de Cache <span id="cache-dependencies"></span> |
||||
|
||||
Além da definição de expiração, um registro em cache pode também ser invalidado por mudanças nas, então chamadas, |
||||
*dependências de cache*. Por exemplo, [[yii\caching\FileDependency]] representa a dependência na data de modificação |
||||
de um arquivo. |
||||
Quando esta dependência muda, significa que o arquivo correspondente foi mudado. Como um resultado, qualquer |
||||
arquivo com data ultrapassada encontrado no cache deve ser invalidado e a chamada de [[yii\caching\Cache::get()|get()]] |
||||
retornará `false`. |
||||
|
||||
Dependências de Cache são representadas como objetos de classes dependentes de [[yii\caching\Dependency]]. Quando você chamar [[yii\caching\Cache::set()|set()]] para armazenar um registro em cache, você pode passar um objeto de dependência. Por exemplo, |
||||
|
||||
```php |
||||
// Criar uma dependência sobre a data de modificação do arquivo exemplo.txt. |
||||
$dependencia = new \yii\caching\FileDependency(['fileName' => 'exemplo.txt']); |
||||
|
||||
// O registro irá expirar em 30 segundos. |
||||
// Ele também pode ser invalidado antes, caso o exemplo.txt seja modificado. |
||||
$cache->set($key, $data, 30, $dependency); |
||||
|
||||
// O cache irá verificar se o registro expirou. |
||||
// E também irá vefiricar se a dependência associada foi alterada. |
||||
// Ele retornará false se qualquer uma dessas condições seja atingida. |
||||
$data = $cache->get($key); |
||||
``` |
||||
Abaixo um sumário das dependências de cache disponíveis: |
||||
|
||||
- [[yii\caching\ChainedDependency]]: a dependência muda caso alguma das dependencias na cadeia for alterada. |
||||
- [[yii\caching\DbDependency]]: a dependência muda caso o resultado da consulta especificada pela instrução SQL seja |
||||
alterado. |
||||
- [[yii\caching\ExpressionDependency]]: a dependencia muda se o resultado da expressão PHP especificada for alterado. |
||||
- [[yii\caching\FileDependency]]: A dependencia muda se a data da última alteração do arquivo for alterada. |
||||
- [[yii\caching\TagDependency]]: associa um registro em cache com uma ou múltiplas tags. Você pode invalidar os |
||||
registros em cache com a tag especificada ao chamar [[yii\caching\TagDependency::invalidate()]]. |
||||
|
||||
|
||||
## Cache de Consulta <span id="query-caching"></span> |
||||
|
||||
Cache de consulta é uma funcionalidade especial de cache construida com o cache de dados. Ela é fornecida para armazenar em cache consultas ao banco de dados. |
||||
|
||||
O cache de consulta requere uma [[yii\db\Connection|DB connection]] e um [componente de aplicação](#cache-components) de `cache` válido. |
||||
A seguir um usu básico de cache de consulta, assumindo que `$bd` é uma instância de [[yii\db\Connection]]: |
||||
|
||||
```php |
||||
$resultado = $bd->cache(function ($bd) { |
||||
|
||||
// O resultado da consulta SQL será entregue pelo cache |
||||
// se o cache de consulta estiver sido habilitado e o resultado da consulta for encontrado em cache |
||||
return $bd->createCommand('SELECT * FROM clientes WHERE id=1')->queryOne(); |
||||
|
||||
}); |
||||
``` |
||||
|
||||
Cache de consulta pode ser usado pelo [DAO](db-dao.md) da mesma forma que um [ActiveRecord](db-active-record.md): |
||||
|
||||
```php |
||||
$resultado = Cliente::getDb()->cache(function ($bd) { |
||||
return Cliente::find()->where(['id' => 1])->one(); |
||||
}); |
||||
``` |
||||
|
||||
> Info: Alguns SGBDs (ex. [MySQL](http://dev.mysql.com/doc/refman/5.1/en/query-cache.html)) |
||||
também suportam o cache de consulta no servidor. Você pode escolher usálo ao invés do mecanismo de cache |
||||
de consulta. |
||||
O cache de consulta descrito acima tem a vantagem de que você pode especificar dependencias de cache flexíveis |
||||
e assim sendo potencialmente mais eficiente. |
||||
|
||||
|
||||
### Configurações <span id="query-caching-configs"></span> |
||||
|
||||
Cache de consulta tem três opções configuraveis globalmente através de [[yii\db\Connection]]: |
||||
|
||||
* [[yii\db\Connection::enableQueryCache|enableQueryCache]]: Configura se o cache de consulta está habilitado. |
||||
O padrão é true. Note que para ter efetivamente o cache de consulta habilitado, você também deve ter um cache válido como especificado por [[yii\db\Connection::queryCache|queryCache]]. |
||||
* [[yii\db\Connection::queryCacheDuration|queryCacheDuration]]: representa o número de segundos que o resultado de uma |
||||
consulta pode se manter válido em cache. Você pode usar 0 para indicar que o resultado da consulta deve permancer no |
||||
cache indefinidamente. Este é o valor padrão usado quando [[yii\db\Connection::cache()]] é chamado sem nenhuma |
||||
especificação de duração. |
||||
* [[yii\db\Connection::queryCache|queryCache]]: representa a ID do componente de aplicação de cache. |
||||
Seu padrão é `'cache'`. Cache de consulta é habilitado apenas se houver um componente de aplicacão de cache válido. |
||||
|
||||
|
||||
### Usando o Cache de Consulta <span id="query-caching-usages"></span> |
||||
|
||||
Você pode usar [[yii\db\Connection::cache()]] se tiver múltiplas consultas SQL que precisam ser armazenadas no |
||||
cache de consulta. Use da seguinte maneira, |
||||
|
||||
```php |
||||
$duracao = 60; // armazenar os resultados em cache por 60 segundos |
||||
$dependencia = ...; // alguma dependencia opcional |
||||
|
||||
$result = $db->cache(function ($db) { |
||||
|
||||
// ... executar consultas SQL aqui ... |
||||
|
||||
return $result; |
||||
|
||||
}, $duracao, $dependencia); |
||||
``` |
||||
|
||||
Qualquer consulta SQL na função anonima irá ser armazenada em cache pela duração especificada com a dependência informada. Se o resultado da consulta for encontrado em cache e for válido, a consulta não será necessária e o |
||||
resultado será entregue pelo cache. Se você não especificar o parametro `$duracao`, o valor de |
||||
[[yii\db\Connection::queryCacheDuration|queryCacheDuration]] será usado. |
||||
|
||||
Ocasionalmente em `cache()`, você pode precisar desabilitar o cache de consulta para algumas consultas em particular. Você pode usar [[yii\db\Connection::noCache()]] neste caso. |
||||
|
||||
```php |
||||
$result = $db->cache(function ($db) { |
||||
|
||||
// consultas SQL que usarão o cache de consulta |
||||
|
||||
$db->noCache(function ($db) { |
||||
|
||||
// consultas SQL que não usarão o cache de consulta |
||||
|
||||
}); |
||||
|
||||
// ... |
||||
|
||||
return $result; |
||||
}); |
||||
``` |
||||
|
||||
Se você apenas deseja usar o cache de consulta para apenas uma consulta, você pode chamar [[yii\db\Command::cache()]] |
||||
ao construir o comando. Por exemplo, |
||||
|
||||
```php |
||||
// usar cache de consulta and definir duração do cache para 60 segundos |
||||
$customer = $db->createCommand('SELECT * FROM customer WHERE id=1')->cache(60)->queryOne(); |
||||
``` |
||||
|
||||
Você pode também usar [[yii\db\Command::noCache()]] para desabilitar o cache de consulta para um único comando, Por exemplo, |
||||
|
||||
```php |
||||
$result = $db->cache(function ($db) { |
||||
|
||||
// consultas SQL que usam o cache de consulta |
||||
|
||||
// não usar cache de consulta para este comando |
||||
$customer = $db->createCommand('SELECT * FROM customer WHERE id=1')->noCache()->queryOne(); |
||||
|
||||
// ... |
||||
|
||||
return $result; |
||||
}); |
||||
``` |
||||
|
||||
|
||||
### Limitações <span id="query-caching-limitations"></span> |
||||
|
||||
O cache de consulta não funciona com resultados de consulta que contêm <i>manipuladores de recursos</i>(resource handlers). |
||||
Por exemplo, ao usar o tipo de coluna `BLOB` em alguns SGBDs, o resultado da consulta irá retornar um <i>manipulador de recurso</i>(resource handler) para o registro na coluna. |
||||
|
||||
Alguns armazenamentos em cache têm limitações de tamanho. Por exemplo, memcache limita o uso máximo de espaço de 1MB para cada registro. Então, se o tamanho do resultado de uma consulta exceder este limite, o cache irá falhar. |
||||
|
@ -0,0 +1,166 @@
|
||||
Cache de Fragmentos |
||||
================ |
||||
|
||||
Cache de fragmentos é responsável por armazenar em cache um fragmento de uma página web. Por exemplo, se uma |
||||
página exibe o sumario de vendas anuais em uma tabela, você pode armazenar esta tabela em cache para eliminar |
||||
o tempo necessário para gerar esta tabela para em cada requisição. O Cache de Fragmentos é construido a partir |
||||
do [cache de dados](caching-data.md). |
||||
|
||||
Para usar o cache de fragmentos, use o seguinte modelo em uma [view](structure-views.md): |
||||
|
||||
```php |
||||
if ($this->beginCache($id)) { |
||||
|
||||
// ... gere o conteúdo aqui ... |
||||
|
||||
$this->endCache(); |
||||
} |
||||
``` |
||||
Ou seja, encapsule a lógica de geração do conteudo entre as chamadas [[yii\base\View::beginCache()|beginCache()]] |
||||
e [[yii\base\View::endCache()|endCache()]]. Se o conteúdo for encontrado em cache, [[yii\base\View::beginCache()|beginCache()]] irá renderizar o conteúdo em cache e retornará falso, e assim não executará a lógica de geração de conteúdo. |
||||
Caso contrário, o conteúdo será gerado, e quando [[yii\base\View::endCache()|endCache()]] for chamado, o conteúdo gerado será capturado e armazenado no cache. |
||||
|
||||
Assim como [cache de dados](caching-data.md), uma `$id` única é necessária para identificar um conteúdo no cache. |
||||
|
||||
|
||||
## Opções do Cache <span id="caching-options"></span> |
||||
|
||||
Você poderá especificar opções adicionais sobre o cache de fragmentos passando um array de opções como o segundo parâmetro do método [[yii\base\View::beginCache()|beginCache()]]. Por trás dos panos, este array de opções será usado para configurar um widget [[yii\widgets\FragmentCache]] que implementa, por sua vez, a funcionalidade de cache de fragmentos. |
||||
|
||||
### Duração <span id="duration"></span> |
||||
|
||||
Esta talvez a opção mais frequentemente usada com cache de fragmentos seja a |
||||
[[yii\widgets\FragmentCache::duration|duration]]. |
||||
Ela especifica por quantos segundos o conteúdo pode permanecer válido no cache. O código a seguir armazena em cache o fragmento do conteúdo por até uma hora: |
||||
|
||||
```php |
||||
if ($this->beginCache($id, ['duration' => 3600])) { |
||||
|
||||
// ... gerar o conteúdo aqui ... |
||||
|
||||
$this->endCache(); |
||||
} |
||||
``` |
||||
|
||||
Se a opção não for definida, o padrão definido é 60, que significa que o conteúdo em cache expirará em 60 segundosnds. |
||||
|
||||
### Dependências <span id="dependencies"></span> |
||||
|
||||
Assim como [cache de dados](caching-data.md#cache-dependencies), o fragmento de conteúdo sendo armazenado em cache pode ter dependencias. |
||||
Por exemplo, o conteúdo de um post sendo exibido depende de ele ter sido ou não modificado. |
||||
|
||||
Para especificar uma dependencia, defina a opção [[yii\widgets\FragmentCache::dependency|dependency]], que pode |
||||
ser um objeto [[yii\caching\Dependency]] ou um array de configuração para criar um objeto de dependência. |
||||
O código a seguir especifica que o conteudo do fragmento depende do valor da coluna `atualizado_em`: |
||||
|
||||
```php |
||||
$dependency = [ |
||||
'class' => 'yii\caching\DbDependency', |
||||
'sql' => 'SELECT MAX(atualizado_em) FROM post', |
||||
]; |
||||
|
||||
if ($this->beginCache($id, ['dependency' => $dependency])) { |
||||
|
||||
// ... gere o conteúdo aqui ... |
||||
|
||||
$this->endCache(); |
||||
} |
||||
``` |
||||
|
||||
|
||||
### Variações <span id="variations"></span> |
||||
|
||||
O Conteúdo armazenado em cache pode variar de acordo com alguns parâmetros. Por exemplo, para uma aplicação web |
||||
suportando múltiplas linguas, a mesma porção de código de uma view pode gerar conteúdo em diferentes línguagem. |
||||
Desta forma, você pode desejar que o código em cache exiba um conteúdo diferente para a línguagem exibida na requisição. |
||||
|
||||
Para especificar variações de cache, defina a opção [[yii\widgets\FragmentCache::variations|variations]], |
||||
que pode ser um array de valores escalares, cada um representando um fator de variação particular. |
||||
Por exemplo, para fazer o conteúdo em cache variar em função da linguagem, você pode usar o seguinte código: |
||||
|
||||
```php |
||||
if ($this->beginCache($id, ['variations' => [Yii::$app->language]])) { |
||||
|
||||
// ... gerar o conteúdo aqui ... |
||||
|
||||
$this->endCache(); |
||||
} |
||||
``` |
||||
|
||||
|
||||
### <i>Cache Alternante</i>(Toggling Caching) <span id="toggling-caching"></span> |
||||
|
||||
Em alguns casos, você pode precisar habilitar o cache de fragmentos somente quando certas condições se aplicam. |
||||
Por exemplo, para uma página exibindo um formulário, e você deseja armazenar o formulário em cache apenas na |
||||
primeira requisição (via requisição GET). Qualquer exibição subsequente (via requisição POST) ao formulário não |
||||
deve ser armazenada em cache porque o formulário pode conter os dados submetidos pelo usuário. Para assim fazê-lo, |
||||
você pode definir a opção [[yii\widgets\FragmentCache::enabled|enabled]], da seguinte maneira: |
||||
|
||||
```php |
||||
if ($this->beginCache($id, ['enabled' => Yii::$app->request->isGet])) { |
||||
|
||||
// ... gerar conteudo aqui ... |
||||
|
||||
$this->endCache(); |
||||
} |
||||
``` |
||||
|
||||
|
||||
## <i>Cache Aninhado</i>(Nested Caching) <span id="nested-caching"></span> |
||||
|
||||
Cache de fragmentos pode ser aninhado. Isto é, um fragmento em cache pode estar contido em outro fragmento que também está em cache. Por exemplo, os comentários estão sendo armazenados em um cache de fragmento inserido em conjunto com o conteudo do post em um outro cache de fragmento. O código a seguir exibe como dois caches de fragmento podem ser aninhados. |
||||
|
||||
```php |
||||
if ($this->beginCache($id1)) { |
||||
|
||||
// ...lógica de geração de conteúdo... |
||||
|
||||
if ($this->beginCache($id2, $options2)) { |
||||
|
||||
// ...lógica de geração de conteúdo... |
||||
|
||||
$this->endCache(); |
||||
} |
||||
|
||||
// ...lógica de geração de conteúdo... |
||||
|
||||
$this->endCache(); |
||||
} |
||||
``` |
||||
|
||||
Diferentes opções de cache podem ser definidas para os caches aninhados. Por exemplo, o cache interior e o cache |
||||
exterior podem ter tempos diferentes de expiração. Mesmo quando um registro no cache exterior é invalidado, o cache |
||||
interior ainda pode permanecer válido. Entretanto, o inverso não pode acontecer. Se o cache exterior é identificado |
||||
como validado, ele continuará a servir a mesma copia em cache mesmo após o conteudo no cache interior ter sido |
||||
invalidado. Desta forma, você deve ser cuidadoso ao definir durações ou dependencias para os caches aninhados, |
||||
já que os fragmentos interiores ultrapassados podem ser mantidos no fragmento externo. |
||||
|
||||
|
||||
## Conteúdo Dinâmico <span id="dynamic-content"></span> |
||||
|
||||
Ao usar o cache de fragmentos, vocế pode encontrar-se na situação em que um grande fragmento de conteúdo é |
||||
relativamente estático exceto em alguns poucos lugares. Por exemplo, um cabeçalho de uma página pode exibir |
||||
a barra do menu principal junto ao nome do usuário logado. Outro problema é que o conteudo sendo armazenado em cache |
||||
pode conter código PHP que deve ser executado para cada requisição (ex. o código para registrar um <i>pacote de recursos estáticos</i>(asset bundles)). Ambos os problemas podem ser resolvidos com a funcionalidade, então chamada de *Conteúdos Dinâmicos*. |
||||
|
||||
Um conteúdo dinâmico compreende um fragmento de uma saida que não deveria ser armazenada em cache mesmo que esteja encapsulada em um cache de fragmento. Para fazer o conteúdo dinâmico indefinidamente, este deve ser gerado pela execução de |
||||
algum código PHP em cada requisição, mesmo que o conteúdo encapsulado esteja sendo servido do cache. |
||||
|
||||
Vocế pode chamar [[yii\base\View::renderDynamic()]] dentro de um cache de fragmento para inserir conteúdo dinâmico no local desejado, como o seguinte, |
||||
|
||||
```php |
||||
if ($this->beginCache($id1)) { |
||||
|
||||
// ...lógica de geração de conteúdo... |
||||
|
||||
echo $this->renderDynamic('return Yii::$app->user->identity->name;'); |
||||
|
||||
// ...lógica de geração de conteúdo... |
||||
|
||||
$this->endCache(); |
||||
} |
||||
``` |
||||
|
||||
O método [[yii\base\View::renderDynamic()|renderDynamic()]] recebe uma porção de código PHP como parâmetro. |
||||
O valor retornado pelo código PHP é tratado como conteúdo dinâmico. O mesmo código PHP será executado em |
||||
cada requisição, não importando se este esteja encapsulado em um fragmento em cache ou não. |
@ -0,0 +1,134 @@
|
||||
Cache HTTP |
||||
============ |
||||
|
||||
Além do cache no servidor que nós descrevemos nas seções anteriores, aplicações web pode também aproveitar-se |
||||
de cache no cliente para economizar o tempo para gerar e transmitir o mesmo conteúdo de uma página. |
||||
|
||||
Para usar o cache no cliente, vocế poderá configurar [[yii\filters\HttpCache] como um filtro para actions de um |
||||
controller ao qual o resultado de sua renderização possa ser armazenado em cache no navegador do cliente. [[yii\filters\HttpCache|HttpCache]] funciona apenas para requisições `GET` e `HEAD`. Ele pode manipular três tipos de cache relacionados a cabeçalhos HTTP para estas requisições: |
||||
|
||||
* [[yii\filters\HttpCache::lastModified|Last-Modified]] |
||||
* [[yii\filters\HttpCache::etagSeed|Etag]] |
||||
* [[yii\filters\HttpCache::cacheControlHeader|Cache-Control]] |
||||
|
||||
|
||||
## Cabeçalho de `Last-modified` <span id="last-modified"></span> |
||||
|
||||
O cabeçalho `Last-modified` usa uma data(timestamp) para indicar se a página foi modificada desde que o cliente a armazenou em cache. |
||||
|
||||
Você pode configurar a propriedade [[yii\filters\HttpCache::lastModified]] para permitir enviar o cabeçalho de `Last-modified`. A propriedade deve ser um <i>callable</i> PHP retornando uma data(timestamp) UNIX sobre o tempo de modificação. A declaração do <i>callable</i> PHP deve ser a seguinte, |
||||
|
||||
```php |
||||
/** |
||||
* @param Action $action O Objeto da action que está sendo manipulada no momento |
||||
* @param array $params o valor da propriedade "params" |
||||
* @return integer uma data(timestamp) UNIX timestamp representando o tempo da |
||||
* última modificação na página |
||||
*/ |
||||
function ($action, $params) |
||||
``` |
||||
|
||||
A seguir um exemplo que faz o uso do cabeçalho `Last-modified`: |
||||
|
||||
```php |
||||
public function behaviors() |
||||
{ |
||||
return [ |
||||
[ |
||||
'class' => 'yii\filters\HttpCache', |
||||
'only' => ['index'], |
||||
'lastModified' => function ($action, $params) { |
||||
$q = new \yii\db\Query(); |
||||
return $q->from('post')->max('updated_at'); |
||||
}, |
||||
], |
||||
]; |
||||
} |
||||
``` |
||||
O código acima afirma que o cache HTTP deve ser habilitado apenas para a action `index`. Este deve |
||||
gerar um cabeçalho HTTP `last-modified` baseado na última data de alteração dos posts. Quando um |
||||
navegador visitar a página `index` pela primeira vez, a página irá ser gerada no servidor e enviada para |
||||
o navegador; Se o navegador visitar a mesma página novamente e não houver modificação dos posts durante este |
||||
período, o servidor não irá re-gerar a página, e o navegador irá usar a versão em cache no cliente. |
||||
Como um resultado a renderização do conteúdo na página não será executada no servidor. |
||||
|
||||
|
||||
## Cabeçalho `ETag` <span id="etag"></span> |
||||
|
||||
O cabeçalho <i>"Entity Tag"</i> (ou `ETag` abreviado) usa um hash para representar o conteúdo de uma página. |
||||
Se a página for alterada, o hash irá mudar também. Ao comparar o hash mantido no cliente com o hash gerado no |
||||
servidor, o cache pode determinar se a página foi alterada e se deve ser re-transmitida. |
||||
|
||||
Você pode configurar a propriedade [[yii\filters\HttpCache::etagSeed]] para habilitar o envio do cabeçalho `ETag`. |
||||
A propriedade deve ser um <i>callable</i> PHP retornando a <i>semente(seed)</i> para a geração do hash do Etag. A declaração do <i>callable</i> PHP deve ser como a seguinte, |
||||
|
||||
```php |
||||
/** |
||||
* @param Action $action o objeto da action que está sendo manipulada no momento |
||||
* @param array $params o valor da propriedade "params" |
||||
* @return string uma string usada como a semente(seed) para gerar um hash ETag |
||||
*/ |
||||
function ($action, $params) |
||||
``` |
||||
|
||||
A Seguir um exemplo que faz o uso do cabeçalho `ETag`: |
||||
|
||||
```php |
||||
public function behaviors() |
||||
{ |
||||
return [ |
||||
[ |
||||
'class' => 'yii\filters\HttpCache', |
||||
'only' => ['view'], |
||||
'etagSeed' => function ($action, $params) { |
||||
$post = $this->findModel(\Yii::$app->request->get('id')); |
||||
return serialize([$post->title, $post->content]); |
||||
}, |
||||
], |
||||
]; |
||||
} |
||||
``` |
||||
|
||||
O código acima afirma que o cache de HTTP deve ser habilitado apenas para a action `view`. Este deve |
||||
gerar um cabeçalho HTTP `ETag` baseado no titulo e conteúdo do post requisitado. Quando um navegador visitar |
||||
a página `view` pela primeira vez, a página será gerada no servidor e enviada para ele; Se o navegador visitar |
||||
a mesma página novamente e não houver alteração para o título e o conteúdo do post, o servidor não irá ré-gerar |
||||
a página, e o navegador irá usar a versão que estiver no cache do cliente. Como um resultado a renderização do |
||||
conteúdo na página não será executada no servidor. |
||||
|
||||
ETags permite estratégias mais complexas e/ou mais precisas do que o uso do cabeçalho de `Last-modified`. |
||||
Por exemplo, um ETag pode ser invalidado se o site tiver sido alterado para um novo tema. |
||||
|
||||
Gerações muito complexas de ETags podem contrariar o propósito de se usar `HttpCache` e introduzir despesas desnecessárias ao processamento, já que eles precisam ser re-avaliados a cada requisição. |
||||
Tente encontrar uma expressão simples que invalida o cache se o conteúdo da página for modificado. |
||||
|
||||
> Observação: Em complacência com a [RFC 7232](http://tools.ietf.org/html/rfc7232#section-2.4), |
||||
`HttpCache` irá enviar os cabeçalhos `ETag` e `Last-Modified` se ambos forem assim configurados. |
||||
E se o cliente envia ambos o cabeçalhos `If-None-Match` e `If-Modified-Since`, apenas o primeiro será |
||||
respeitado. |
||||
|
||||
|
||||
## Cabeçalho `Cache-Control` <span id="cache-control"></span> |
||||
|
||||
O cabeçalho `Cache-Control` especifica politicas de cache gerais para as páginas. Você pode enviá-lo configurando a propriedade [[yii\filters\HttpCache::cacheControlHeader]] com o valor do cabeçalho. Por padrão, o seguinte cabeçalho será enviado: |
||||
|
||||
``` |
||||
Cache-Control: public, max-age=3600 |
||||
``` |
||||
|
||||
## Limitador de Cache na Sessão <span id="session-cache-limiter"></span> |
||||
|
||||
Quando uma página usa sessão, o PHP irá automaticamente enviar alguns cabeçalhos HTTP relacionados ao cache |
||||
como especificado na configuração do PHP INI `session.cache_limiter`. Estes cabeçalhos podem inteferirir ou |
||||
desabilitar o cache que você deseja do `HttpCache`. Para previnir-se deste problema, por padrão `HttpCache` |
||||
irá desabilitar o envio destes cabeçalhos automaticamente. Se você quiser modificar estes comportamente, deve |
||||
configurara a propriedade [[yii\filters\HttpCache::sessionCacheLimiter]]. A propriedade pode receber um valor em uma string, incluindo `public`, `private`, `private_no_expire`, e `nocache`. Por favor referir-se ao manual do |
||||
PHP sobre [session_cache_limiter()](http://www.php.net/manual/en/function.session-cache-limiter.php) |
||||
para explicações sobre estes valores. |
||||
|
||||
|
||||
## Implicações para SEO <span id="seo-implications"></span> |
||||
|
||||
Os bots do motor de buscas tendem a respeitar cabeçalhos de cache. Ja que alguns rastreadores têm um limite sobre a quantidade de páginas por dominio que eles processam em um certo espaço de tempo, introduzir cabeçalhos de cache podem |
||||
ajudar na indexação do seu site já que eles reduzem o número de páginas que precisam ser processadas. |
||||
|
@ -0,0 +1,17 @@
|
||||
Cache |
||||
======= |
||||
|
||||
Cache é uma maneira barata e eficiente de melhorar o desempenho de uma aplicação web. Ao gravar dados relativamente |
||||
estáticos em cache e servindo os do cache quando requisitados, a aplicação economiza o tempo que seria necessário |
||||
para renderizar as informações do zero toda vez. |
||||
|
||||
Cache pode ocorrer em diferentes níveis e locais em uma aplicação web. No servidor, no baixo nível, |
||||
cache pode ser usado para armazenar dados básicos, como a informação de uma lista de artigos mais recentes trazidos |
||||
do banco de dados; e no alto nível, cache pode ser usado para armazenar fragmentos ou páginas web inteiras,como o |
||||
resultado da renderização dos artigos mais recentes. No cliente, cache HTTP pode ser usado para manter o conteúdo da última página acessada no cache do navegador. |
||||
|
||||
Yii suporta todos os os três métodos de cache: |
||||
* [Cache de Dados](caching-data.md) |
||||
* [Cache de Fragmento](caching-fragment.md) |
||||
* [Cache de Página](caching-page.md) |
||||
* [Cache de HTTP](caching-http.md) |
@ -0,0 +1,38 @@
|
||||
Cache de Página |
||||
============ |
||||
|
||||
O Cache de página é responsável por armazenar em cache o conteúdo de uma página inteira no servidor. Mais tarde, |
||||
quando a mesma página é requisitada novamente, seu conteúdo será servido do cache em vez de ela ser gerada novamente |
||||
do zero. |
||||
|
||||
O Cache de página é implementado pela classe [[yii\filters\PageCache]], um [filtro de actions](structure-filters.md). |
||||
Esta pode ser usada da seguinte maneira em uma classe de controller: |
||||
|
||||
```php |
||||
public function behaviors() |
||||
{ |
||||
return [ |
||||
[ |
||||
'class' => 'yii\filters\PageCache', |
||||
'only' => ['index'], |
||||
'duration' => 60, |
||||
'variations' => [ |
||||
\Yii::$app->language, |
||||
], |
||||
'dependency' => [ |
||||
'class' => 'yii\caching\DbDependency', |
||||
'sql' => 'SELECT COUNT(*) FROM post', |
||||
], |
||||
], |
||||
]; |
||||
} |
||||
``` |
||||
O código acima afirma que o cache de página deve ser usado apenas para a action `index`; o conteúdo da página deve |
||||
ser armazenado em cache por, no máximo, 60 segundos e deve variar de acordo com a linguagem atual da aplicação; |
||||
e esta página em cache deve ser invalidada se o número total de posts for alterado. |
||||
|
||||
Como vocế pode ver, o cache de página é bastante similar ao [cache de fragmentos](caching-fragment.md). Ambos suportam opções como `duration`, `dependencies`, `variations`, and `enabled`. Sua principal diferença é que o cache de página implementado como um [filtro de actions](structure-filters.md) enquanto que o cache de fragmentos é um [widget](structure-widgets.md). |
||||
|
||||
Você pode usar o [cache de fragmentos](caching-fragment.md) ou [conteúdo dinâmico](caching-fragment.md#dynamic-content) |
||||
em conjunto com o cache de página. |
||||
|
@ -0,0 +1,123 @@
|
||||
Aliases(Apelidos) |
||||
======= |
||||
|
||||
Aliases são usados para representar caminhos de arquivos ou URLs de forma que você não precise acoplar o código usando caminhos absolutos ou URLs em seu projeto. Um alias deve começar com o caractere `@` para se diferenciar de um caminho de arquivo normal ou URL. Yii já possui vários aliases predefinidos disponíveis. |
||||
Por exemplo, o alias `@yii` representa o local em que o framework Yii foi instalado; `@web` representa a URL base para a aplicação que está sendo executada no momento. |
||||
|
||||
|
||||
Definindo Aliases <span id="defining-aliases"></span> |
||||
---------------- |
||||
|
||||
Você pode definir um alias para um caminho de arquivo ou URL chamando [[Yii::setAlias()]]: |
||||
|
||||
```php |
||||
// um alias de um caminho de arquivo |
||||
Yii::setAlias('@foo', '/caminho/para/foo'); |
||||
|
||||
// um alias de uma URL |
||||
Yii::setAlias('@bar', 'http://www.exemplo.com.br'); |
||||
``` |
||||
|
||||
> Observação: O caminho do arquivo ou URL sendo <i>apelidado</i>(aliased) *não* necessariamente refere-se a um arquivo ou a recursos existentes. |
||||
|
||||
Dado um alias definido, você pode derivar um novo alias (sem a necessidade de chamar [[Yii::setAlias()]]) apenas acrescentando uma barra `/` seguido de um ou mais segmentos de caminhos de arquivos. Os aliases definidos através de [[Yii::setAlias()]] tornam-se o *alias raiz*(root alias), enquanto que aliases derivados dele, tornam-se *aliases derivados*. Por exemplo, `@foo` é um <i>alias raiz</i>(root alias), enquanto `@foo/bar/arquivo.php` é um alias derivado. |
||||
|
||||
Você pode definir um alias usando outro alias (tanto raiz quanto derivado): |
||||
|
||||
```php |
||||
Yii::setAlias('@foobar', '@foo/bar'); |
||||
``` |
||||
|
||||
Aliases raiz são normalmente definidos durante o estágio de [inicialização](runtime-bootstrapping.md). |
||||
Por exemplo, você pode chamar [[Yii::setAlias()]] no [script de entrada](structure-entry-scripts.md). |
||||
Por conveniência, as [Aplicações](structure-applications.md) difinem uma propriedade `aliases` que você |
||||
pode configurar na [configuração](concept-configurations.md) da aplicação: |
||||
|
||||
```php |
||||
return [ |
||||
// ... |
||||
'aliases' => [ |
||||
'@foo' => '/caminho/para/foo', |
||||
'@bar' => 'http://www.exemplo.com.br', |
||||
], |
||||
]; |
||||
``` |
||||
|
||||
|
||||
Resolvendo Aliases <span id="resolving-aliases"></span> |
||||
----------------- |
||||
|
||||
Você pode chamar [[Yii::getAlias()]] em um alias raiz para resolver o caminho de arquivo ou URL que ele representa. |
||||
O mesmo método pode tambem, resolver um alias derivado em seu caminho de arquivo ou URL correspondente. |
||||
|
||||
```php |
||||
echo Yii::getAlias('@foo'); // exibe: /caminho/para/foo |
||||
echo Yii::getAlias('@bar'); // exibe: http://www.example.com |
||||
echo Yii::getAlias('@foo/bar/arquivo.php'); // exibe: /caminho/para/foo/bar/arquivo.php |
||||
``` |
||||
|
||||
O caminho/URL representado por um alias derivado é determinado substituindo a parte do alias raiz com o seu caminho/URL correspondente. |
||||
|
||||
> Observação: O método [[Yii::getAlias()]] não checa se o caminho/URL resultante refere-se a um arquivo ou recursos existentes. |
||||
|
||||
|
||||
Um alias raiz pode também conter caracteres de barra `/`. O método [[Yii::getAlias()]] é inteligente o suficiente |
||||
para descobrir que parte de um alias é um alias raiz e assim determina o caminho de arquivo ou URL correspondente: |
||||
|
||||
```php |
||||
Yii::setAlias('@foo', '/caminho/para/foo'); |
||||
Yii::setAlias('@foo/bar', '/caminho2/bar'); |
||||
Yii::getAlias('@foo/test/arquivo.php'); // exibe: /caminho/para/foo/test/arquivo.php |
||||
Yii::getAlias('@foo/bar/arquivo.php'); // exibe: /caminho2/bar/arquivo.php |
||||
``` |
||||
|
||||
Se `@foo/bar` não estivesse definido como um alias raiz, a última chamada exibiria `/caminho/para/foo/bar/arquivo.php`. |
||||
|
||||
|
||||
Usando Aliases <span id="using-aliases"></span> |
||||
------------- |
||||
|
||||
Aliases são reconhecidos em muitos lugares no Yii sem a necessidade de chamar [[Yii::getAlias()]] para convertê-los em caminhos e URLs. Por exemplo, [[yii\caching\FileCache::cachePath]] pode aceitar tanto um caminho de arquivo quanto um alias representando o caminho do arquivo, graças ao prefíxo `@` que nos permite diferenciar um caminho de arquivo de um alias. |
||||
|
||||
```php |
||||
use yii\caching\FileCache; |
||||
|
||||
$cache = new FileCache([ |
||||
'cachePath' => '@runtime/cache', |
||||
]); |
||||
``` |
||||
|
||||
Por favor preste atenção a documentação da API para saber se o parâmetro de uma propriedade ou método suporta aliases. |
||||
|
||||
|
||||
Aliases Predefinidos <span id="predefined-aliases"></span> |
||||
------------------ |
||||
|
||||
Yii já predefine uma gama de aliases para referenciar facilmente caminhos de arquivos e URLs comumente usados: |
||||
|
||||
- `@yii`, o diretório onde o arquivo `BaseYii.php` está localizado (também chamado de diretório do framework). |
||||
- `@app`, o caminho base [[yii\base\Application::basePath|base path]] da aplicação sendo executada no momento. |
||||
- `@runtime`, o caminho em <i>tempo de execução</i>(runtime) [[yii\base\Application::runtimePath|runtime path]] da aplicação sendo |
||||
executada no momento. |
||||
- `@webroot`, o diretório webroot da aplicação sendo executada no momento. Este é determinado baseado no diretório |
||||
contendo o [script de entrada](structure-entry-scripts.md). |
||||
- `@web`, a URL base da aplicacão sendo executada no momento. Esta tem o mesmo valor de [[yii\web\Request::baseUrl]]. |
||||
- `@vendor`, o caminho da pasta vendor [[yii\base\Application::vendorPath|Composer vendor directory]]. |
||||
Seu padrão é `@app/vendor`. |
||||
- `@bower`, o caminho raiz que contém os [pacotes bower](http://bower.io/). Seu padrão é `@vendor/bower`. |
||||
- `@npm`, o caminho raiz que contém [pacotes npm](https://www.npmjs.org/). Seu padrão é `@vendor/npm`. |
||||
|
||||
O alias `@yii` é definido quando você inclui o arquivo `Yii.php` em seu [script de entrada](structure-entry-scripts.md). |
||||
O resto dos aliases são definidos no construtor da aplicação ao aplicar a [configuração](concept-configurations.md) da aplicação. |
||||
|
||||
|
||||
Aliases para Extensões <span id="extension-aliases"></span> |
||||
----------------- |
||||
|
||||
Um alias é automaticamente definido para cada [extensão](structure-extensions.md) que for instalada através do Composer. |
||||
Cada alias é nomeado a partir do namespace raiz da extensão como declarada em seu arquivo `composer.json`, e cada alias representa o diretório raiz de seu pacote. Por exemplo, se você instalar a extensão `yiisoft/yii2-jui`, |
||||
você terá automaticamente o alias `@yii/jui` definido durante o estágio de [inicialização](runtime-bootstrapping.md), equivalente a: |
||||
|
||||
```php |
||||
Yii::setAlias('@yii/jui', 'VendorPath/yiisoft/yii2-jui'); |
||||
``` |
@ -0,0 +1,304 @@
|
||||
Behaviors (Comportamentos) |
||||
========= |
||||
|
||||
Behaviors são instâncias de [[yii\base\Behavior]], ou de uma classe-filha, também conhecido como [mixins](http://en.wikipedia.org/wiki/Mixin), permite melhorar a funcionalidade de uma classe [[yii\base\Component|componente]] existente sem a necessidade de mudar a herança dela. |
||||
Anexar um behavior a um componente "introduz" os métodos e propriedades do behavior dentro do componente, tornando esses métodos e propriedades acessíveis como se estes fossem definidos na própria classe do componente. Além disso, um behavior pode responder a um [evento](concept-events.md) disparado pelo componente, o que permite a customização do código normal. |
||||
|
||||
Definindo Behaviors <span id="defining-behaviors"></span> |
||||
------------------ |
||||
|
||||
Para definir um behavior , Crie uma classe extendendo de [[yii\base\Behavior]], ou de uma classe-filha. Por exemplo: |
||||
|
||||
```php |
||||
namespace app\components; |
||||
|
||||
use yii\base\Behavior; |
||||
|
||||
class MyBehavior extends Behavior |
||||
{ |
||||
public $prop1; |
||||
|
||||
private $_prop2; |
||||
|
||||
public function getProp2() |
||||
{ |
||||
return $this->_prop2; |
||||
} |
||||
|
||||
public function setProp2($value) |
||||
{ |
||||
$this->_prop2 = $value; |
||||
} |
||||
|
||||
public function foo() |
||||
{ |
||||
// ... |
||||
} |
||||
} |
||||
``` |
||||
|
||||
O código acima define a classe behavior `app\components\MyBehavior`, com duas propriedades --`prop1` e `prop2`-- e um método `foo()`. Note que a propriedade `prop2` |
||||
É definida através do método getter `getProp2()` e setter `setProp2()`. Isto é possível porque [[yii\base\Behavior]] extende de [[yii\base\Object]] e portanto suporta definição de propriedades através de getters e setters [properties](concept-properties.md). |
||||
|
||||
Como essa classe é um behavior , quando ela está anexada a um componente, então este componente terá as propriedades `prop1` e `prop2` e o método `foo()`. |
||||
|
||||
> Dica: Em um behavior , você pode acessar o componente que o behavior está anexado através da propriedade [[yii\base\Behavior::owner]]. |
||||
|
||||
Manuseando Eventos de Componente |
||||
------------------ |
||||
|
||||
Se um behavior precisa responder a eventos disparados pelo componente ao qual está ligado, este deve sobrescrever o método [[yii\base\Behavior::events()]]. Por exemplo: |
||||
|
||||
```php |
||||
namespace app\components; |
||||
|
||||
use yii\db\ActiveRecord; |
||||
use yii\base\Behavior; |
||||
|
||||
class MyBehavior extends Behavior |
||||
{ |
||||
// ... |
||||
|
||||
public function events() |
||||
{ |
||||
return [ |
||||
ActiveRecord::EVENT_BEFORE_VALIDATE => 'beforeValidate', |
||||
]; |
||||
} |
||||
|
||||
public function beforeValidate($event) |
||||
{ |
||||
// ... |
||||
} |
||||
} |
||||
``` |
||||
O método [[yii\base\Behavior::events()|events()]] deve retornar uma lista de eventos e seus manipuladores correspondentes. |
||||
O exemplo acima declara que o evento [[yii\db\ActiveRecord::EVENT_BEFORE_VALIDATE|EVENT_BEFORE_VALIDATE]] existe e define seu manipulador, `beforeValidate()`. Ao especificar um manipulador de evento, você pode utilizar um dos seguintes formatos: |
||||
|
||||
* uma string que refere-se ao nome do método da classe behavior , como o exemplo acima |
||||
* um array com o nome do objeto ou classe, e um nome de método como string (sem parênteses), por exemplo, `[$object, 'methodName']`; |
||||
* uma função anônima |
||||
|
||||
A assinatura de um manipulador de eventos deve ser como o exemplo abaixo, onde `$event` refere-se ao parâmetro do evento. Por favor, consulte a seção [Events](concept-events.md) para mais detalhes sobre eventos. |
||||
|
||||
```php |
||||
function ($event) { |
||||
} |
||||
``` |
||||
|
||||
Anexando Behaviors (Comportamentos) <span id="attaching-behaviors"></span> |
||||
------------------- |
||||
|
||||
Você pode anexar um behavior a um [[yii\base\Component|component]] de forma estática ou dinâmica. Na prática a forma estática é a mais comum. |
||||
|
||||
Para anexar um behavior de forma estática, sobrescreva o método [[yii\base\Component::behaviors()|behaviors()]] da classe componente |
||||
para o behavior que está sendo anexado. O método [[yii\base\Component::behaviors()|behaviors()]] deveria retornar uma lista de behavior [configurations](concept-configurations.md). |
||||
Cada configuração de behavior pode ser tanto um nome de classe behavior ou um array de configuração: |
||||
|
||||
```php |
||||
namespace app\models; |
||||
|
||||
use yii\db\ActiveRecord; |
||||
use app\components\MyBehavior; |
||||
|
||||
class User extends ActiveRecord |
||||
{ |
||||
public function behaviors() |
||||
{ |
||||
return [ |
||||
// behavior anônimo, somente o nome da classe |
||||
MyBehavior::className(), |
||||
|
||||
// behavior nomeado, somente o nome da classe |
||||
'myBehavior2' => MyBehavior::className(), |
||||
|
||||
// behavior anônimo, array de configuração |
||||
[ |
||||
'class' => MyBehavior::className(), |
||||
'prop1' => 'value1', |
||||
'prop2' => 'value2', |
||||
], |
||||
|
||||
// behavior nomeado, array de configuração |
||||
'myBehavior4' => [ |
||||
'class' => MyBehavior::className(), |
||||
'prop1' => 'value1', |
||||
'prop2' => 'value2', |
||||
] |
||||
]; |
||||
} |
||||
} |
||||
``` |
||||
|
||||
Você pode associar um nome com um behavior especificando a chave do array correspondente à configuração do behavior. Neste caso o behavior é chamado *behavior nomeado*. No exemplo acima existem dois behaviors nomeados: `myBehavior2` e `myBehavior4`. Se um behavior não está associado a um nome, ele é chamado de *behavior anônimo*. |
||||
|
||||
Para anexar um behavior dinâmicamente, execute o método [[yii\base\Component::attachBehavior()]] do component para o behavior que está sendo anexado: |
||||
|
||||
```php |
||||
use app\components\MyBehavior; |
||||
|
||||
// anexando um objeto behavior |
||||
$component->attachBehavior('myBehavior1', new MyBehavior); |
||||
|
||||
// anexando uma classe behavior |
||||
$component->attachBehavior('myBehavior2', MyBehavior::className()); |
||||
|
||||
// anexando através de um array de configuração |
||||
$component->attachBehavior('myBehavior3', [ |
||||
'class' => MyBehavior::className(), |
||||
'prop1' => 'value1', |
||||
'prop2' => 'value2', |
||||
]); |
||||
``` |
||||
|
||||
Você pode anexar vários behaviors de uma só vez usando o método [[yii\base\Component::attachBehaviors()]]: |
||||
|
||||
```php |
||||
$component->attachBehaviors([ |
||||
'myBehavior1' => new MyBehavior, // a named behavior |
||||
MyBehavior::className(), // an anonymous behavior |
||||
]); |
||||
``` |
||||
|
||||
Você também pode anexar behaviors através de [configurations](concept-configurations.md) conforme exemplo abaixo: |
||||
|
||||
```php |
||||
[ |
||||
'as myBehavior2' => MyBehavior::className(), |
||||
|
||||
'as myBehavior3' => [ |
||||
'class' => MyBehavior::className(), |
||||
'prop1' => 'value1', |
||||
'prop2' => 'value2', |
||||
], |
||||
] |
||||
``` |
||||
Para mais detalhes, por favor consulte a seção [Configurations](concept-configurations.md#configuration-format). |
||||
|
||||
Usando Behaviors <span id="using-behaviors"></span> |
||||
--------------- |
||||
|
||||
Para usar um behavior, primeiro este deve ser anexado à um [[yii\base\Component|component]] conforme as instruções acima. Uma vez que o behavior está anexado ao componente, seu uso é simples. |
||||
|
||||
Você pode acessar uma variável *pública* ou uma propriedade [property](concept-properties.md) definida por um getter e/ou um setter do behavior através do componente ao qual ele está anexado: |
||||
|
||||
```php |
||||
// "prop1" é uma propriedade defined na classe behavior |
||||
echo $component->prop1; |
||||
$component->prop1 = $value; |
||||
``` |
||||
|
||||
Você também pode executar um método *público* do behavior de forma parecida: |
||||
|
||||
```php |
||||
// foo() é um método publico definido na classe behavior |
||||
$component->foo(); |
||||
``` |
||||
|
||||
Como você pode ver, embora `$component` não define`prop1` e nem `foo()`, eles podem ser utilizados como se eles fizessem parte da definição do componente, isto se deve ao behavior anexado. |
||||
|
||||
Se dois behaviors definem a mesma propriedade ou método e ambos são anexados ao mesmo componente, o behavior que for anexado primeiramente ao componente terá precedência quando a propriedade ou método for acessada. |
||||
|
||||
Um behavior pode estar associado a um nome quando ele for anexado a um componente. Sendo esse o caso, você pode acessar o objeto behavior usando o name: |
||||
|
||||
```php |
||||
$behavior = $component->getBehavior('myBehavior'); |
||||
``` |
||||
|
||||
Você também pode pegar todos os behaviors anexados a um componente: |
||||
|
||||
```php |
||||
$behaviors = $component->getBehaviors(); |
||||
``` |
||||
|
||||
Desvinculando Behaviors (Comportamentos)<span id="detaching-behaviors"></span> |
||||
------------------- |
||||
|
||||
Para desvincular um behavior, execute [[yii\base\Component::detachBehavior()]] com o nome associado ao behavior: |
||||
|
||||
```php |
||||
$component->detachBehavior('myBehavior1'); |
||||
``` |
||||
|
||||
Você também pode desvincular *todos* os behaviors: |
||||
|
||||
```php |
||||
$component->detachBehaviors(); |
||||
``` |
||||
|
||||
Usando `TimestampBehavior` <span id="using-timestamp-behavior"></span> |
||||
------------------------- |
||||
|
||||
Para encerrar, vamos dar uma olhada [[yii\behaviors\TimestampBehavior]]. Este behavior suporta atualização automática dos atributos timestamp de um [[yii\db\ActiveRecord|Active Record]] toda vez que o model (modelo) for salvo (por exemplo, Inserte ou update). |
||||
|
||||
Primeiro, anexe este behavior na classe [[yii\db\ActiveRecord|Active Record]] que você planeja usar: |
||||
|
||||
```php |
||||
namespace app\models\User; |
||||
|
||||
use yii\db\ActiveRecord; |
||||
use yii\behaviors\TimestampBehavior; |
||||
|
||||
class User extends ActiveRecord |
||||
{ |
||||
// ... |
||||
|
||||
public function behaviors() |
||||
{ |
||||
return [ |
||||
[ |
||||
'class' => TimestampBehavior::className(), |
||||
'attributes' => [ |
||||
ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'], |
||||
ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], |
||||
], |
||||
], |
||||
]; |
||||
} |
||||
} |
||||
``` |
||||
|
||||
A configuração do behavior acima especifica que quando o registro está sendo: |
||||
|
||||
* inserido, o behavior deve atribuir o timestamp atual para os atributos `created_at` e `updated_at` |
||||
* atualizado, o behavior deve atribuir o timestamp atual para o atributo `updated_at` |
||||
|
||||
Com esse código no lugar, se você tem um objeto `User` e tenta salvá-lo, você encontrará seus `created_at` e `updated_at` automáticamente preenchidos com a data e hora atual: |
||||
|
||||
```php |
||||
$user = new User; |
||||
$user->email = 'test@example.com'; |
||||
$user->save(); |
||||
echo $user->created_at; // shows the current timestamp |
||||
``` |
||||
|
||||
O [[yii\behaviors\TimestampBehavior|TimestampBehavior]] também oferece um método útil |
||||
[[yii\behaviors\TimestampBehavior::touch()|touch()]], que irá atribuir a data e hora atual para um atributo específico e salvar o database: |
||||
|
||||
```php |
||||
$user->touch('login_time'); |
||||
``` |
||||
|
||||
Comparando Behaviors com Traits <span id="comparison-with-traits"></span> |
||||
---------------------- |
||||
|
||||
Apesar de behaviors serem semelhantes a [traits](http://www.php.net/traits) em que ambos "injetam" suas propriedades e métodos para a classe principal, eles diferem em muitos aspectos. Tal como explicado abaixo, ambos têm prós e contras. Eles funcionam mais como complemento um do outro. |
||||
|
||||
### Razões para usar Behaviors <span id="pros-for-behaviors"></span> |
||||
|
||||
Classes Behavior, como classes normais, suportam herança. Traits, por outro lado, pode ser só suporta a programação “copia e cola”. Eles não suportam herança. |
||||
|
||||
Behaviors podem ser anexados e desvinculados a um componente dinamicamente sem necessidade de modificação da classe componente. |
||||
Para usar um trait, você deve modificar o código da classe de usá-lo. |
||||
|
||||
Behaviors são configuráveis enquanto traits não são. |
||||
|
||||
Behaviors podem customizar a execução do código do componente respondendo aos seus eventos. |
||||
Quando houver nomes conflitantes entre diferentes behaviors anexados ao mesmo componente, o conflito é automaticamente resolvido priorizando o behavior anexado primeiramente ao componente. Nomes conflitantes causados por diferentes traits requer resolução manual renomeando as propriedades ou métodos afetados. |
||||
|
||||
### Razões para usar Traits <span id="pros-for-traits"></span> |
||||
|
||||
Traits são muito mais eficientes do que behaviors, estes são objetos e requerem mais tempo e memória. |
||||
|
||||
IDEs são mais amigáveis com traits por serem nativos do PHP. |
||||
|
@ -0,0 +1,94 @@
|
||||
Componentes |
||||
=========== |
||||
|
||||
Componente é a parte principal na construção de aplicações Yii. Componentes são instâncias de [[yii\base\Component]], |
||||
Ou uma classe extendida. As três características principais que os Componentes fornecem a outras classes são: |
||||
|
||||
* [Propriedades](concept-properties.md) |
||||
* [Eventos](concept-events.md) |
||||
* [Behaviors (Comportamentos)](concept-behaviors.md) |
||||
|
||||
Separadamente e combinadas, essas características fazem com que as classes no Yii sejam muito mais customizáveis e fáceis de usar. Por Exemplo, |
||||
O include [[yii\jui\DatePicker|date picker widget]], um componete de interface do usuário, pode ser usado na [view (visão)](structure-view.md) |
||||
Para gerar um `date picker` interativo: |
||||
|
||||
```php |
||||
use yii\jui\DatePicker; |
||||
|
||||
echo DatePicker::widget([ |
||||
'language' => 'ru', |
||||
'name' => 'country', |
||||
'clientOptions' => [ |
||||
'dateFormat' => 'yy-mm-dd', |
||||
], |
||||
]); |
||||
``` |
||||
|
||||
Os widgets são facilmente escritos porque a classe estende de [[yii\base\Component]]. |
||||
|
||||
Enquanto componenetese são muito poderosos, eles são um pouco mais pesados do que um objeto normal, devido ao fato de que é preciso |
||||
Memória e CPU extra para dar suporte a [evento](concept-events.md) e [comportamento](concept-behaviors.md) funcionalidade em particular. |
||||
Se o seu componente não precisa dessas duas características, você pode considerar extender a sua classe de componente de [[yii\base\Object]] em vez de [[yii\base\Component]]. Se o fizer, fará com que seus componentes sejam tão eficientes como objetos normais do PHP, |
||||
Mas com um suporte adcional para [propriedades](concept-properties.md). |
||||
|
||||
Ao extender sua classe de [[yii\base\Component]] ou [[yii\base\Object]], é recomendado que você siga estas convenções: |
||||
|
||||
- Se você sobrescrever o construtor, declare um parâmetro `$config` como último parâmetro do construtor, e em seguida passe este parâmetro para o construtor pai. |
||||
- Sempre chame o construtor pai *no final* do seu construtor reescrito. |
||||
- Se você sobrescrever o método [[yii\base\Object::init()]],certifique-se de chamar a implementação pai do `init` *no início* do seu método `init`. |
||||
|
||||
Por Exemplo: |
||||
|
||||
```php |
||||
<?php |
||||
|
||||
namespace yii\components\MyClass; |
||||
|
||||
use yii\base\Object; |
||||
|
||||
class MyClass extends Object |
||||
{ |
||||
public $prop1; |
||||
public $prop2; |
||||
|
||||
public function __construct($param1, $param2, $config = []) |
||||
{ |
||||
// ... initialization before configuration is applied |
||||
|
||||
parent::__construct($config); |
||||
} |
||||
|
||||
public function init() |
||||
{ |
||||
parent::init(); |
||||
|
||||
// ... initialization after configuration is applied |
||||
} |
||||
} |
||||
``` |
||||
|
||||
Seguindo essas orientações fará com que seus componentes sejam [configuraveis](concept-configurations.md) quando forem criados. Por Exemplo: |
||||
|
||||
```php |
||||
$component = new MyClass(1, 2, ['prop1' => 3, 'prop2' => 4]); |
||||
// alternatively |
||||
$component = \Yii::createObject([ |
||||
'class' => MyClass::className(), |
||||
'prop1' => 3, |
||||
'prop2' => 4, |
||||
], [1, 2]); |
||||
``` |
||||
|
||||
> informação: Embora a forma de chamar [[Yii::createObject()]] pareça ser mais complicada, ela é mais poderosa porque ela é |
||||
> aplicada no topo de um [recipiente |
||||
de injeção de dependência](concept-di-container.md). |
||||
|
||||
|
||||
A Classe [[yii\base\Object]] inpõe o seguinte cilo de vida do objeto: |
||||
|
||||
1. Pré-inicialização dentro do construtor. Você pode definir valores de propriedade padrão aqui. |
||||
2. Configuração de objeto via `$config`. A configuração pode sobrescrever o valor padrão configurado dentro do construtor. |
||||
3. Pós-inicialização dentro do [[yii\base\Object::init()|init()]]. Você pode sobrescrever este método para executar checagens e normalização das propriedades. |
||||
4. Chamadas de método de objeto. |
||||
|
||||
Os três primeiros passos acontecem dentro do construtor do objeto. Isto significa que uma vez que você instancia a classe (Isto é, um objeto), esse objeto foi inicializado adequadamente. |
@ -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"). |
@ -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`. |
@ -0,0 +1,421 @@
|
||||
Migrações de Dados (Migrations) |
||||
================== |
||||
|
||||
Durante o curso de desenvolvimento e manutenção de uma aplicação orientada a banco de dados, a estrutura |
||||
de banco sendo usada evolui ao mesmo tempo em que o código. Por exemplo, durante o desenvolvimento de |
||||
uma aplicação, a criação de uma nova tabela pode ser necessária; após ser feito o deploy da aplicação em produção, |
||||
pode ser descoberto que um índice deveria ser criado para melhorar a performance de alguma query; entre |
||||
outros. Como a mudança de uma estrutura de banco de dados normalmente necessita de alguma mudança no código, |
||||
Yii suporta a então chamada funcionalidade de *migração de dados* que permite que você mantenha um registro |
||||
das mudanças feitas no banco de dados em termos de *migrações de dados* que são versionadas em conjunto |
||||
com o código fonte da aplicação. |
||||
|
||||
Os seguintes passos mostram como uma migração de dados pode ser usada pela equipe durante o desenvolvimento: |
||||
|
||||
1. João cria uma nova migração (ex. cria uma nova tabela, muda a definição de uma coluna, etc.). |
||||
2. João comita a nova migração no sistema de controle de versão (ex. Git, Mercurial). |
||||
3. Pedro atualiza seu repositório a partir do sistema de controle de versão e recebe a nova migração. |
||||
4. Pedro aplica a nova migração ao seu banco de dados local em seu ambiente de desenvolvimento, e assim, sincronizando seu banco de dados para refletir as mudanças que João fez. |
||||
|
||||
E os seguintes passos mostram como fazer o deploy para produção de uma nova versão: |
||||
|
||||
1. Luiz cria uma nova tag para o repositório do projeto que contem algumas novas migrações de dados. |
||||
2. Luiz atualiza o código fonte no servidor em produção para a tag criada. |
||||
3. Luiz aplica todas as migrações de dados acumuladas para o banco de dados em produção. |
||||
|
||||
Yii oferece um conjunto de ferramentas de linha de comando que permitem que você: |
||||
|
||||
* crie novas migrações; |
||||
* aplique migrações; |
||||
* reverta migrações; |
||||
* reaplique migrações; |
||||
* exiba um histórico das migrações; |
||||
|
||||
Todas estas ferramentas são acessíveis através do comando `yii migrate`. Nesta seção nós iremos descrever |
||||
em detalhes como realizar várias tarefas usando estas ferramentas. Você também pode descobrir como usar |
||||
cada ferramenta através do comando de ajuda `yii help migrate`. |
||||
|
||||
> Observação: os migrations (migrações) podem afetar não só o esquema do banco de dados, |
||||
mas também ajustar os dados existentes para se conformar ao novo esquema, como |
||||
criar novas hierarquias de RBAC ou limpar dados de cache. |
||||
|
||||
|
||||
## Criando Migrações <span id="creating-migrations"></span> |
||||
|
||||
Para criar uma nova migração, execute o seguinte comando: |
||||
|
||||
``` |
||||
yii migrate/create <nome> |
||||
``` |
||||
|
||||
O argumento obrigatório `nome` serve como uma breve descricão sobre a nova migração. Por exemplo, se |
||||
a migração é sobre a criação de uma nova tabela chamada *noticias*, você pode usar o nome `criar_tabela_noticias` |
||||
e executar o seguinte comando: |
||||
|
||||
``` |
||||
yii migrate/create criar_tabela_noticias |
||||
``` |
||||
|
||||
> Nota: Como o argumento `nome` será usado como parte do nome da classe de migração gerada, este deve |
||||
conter apenas letras, dígitos, e/ou underline. |
||||
|
||||
O comando acima irá criar um novo arquivo contendo uma classe PHP chamada `m150101_185401_criar_tabela_noticias.php` |
||||
na pasta `@app/migrations`. O arquivo contem o seguinte codigo que declara a classe de migração |
||||
`m150101_185401_criar_tabela_noticias` com o código esqueleto: |
||||
|
||||
```php |
||||
<?php |
||||
|
||||
use yii\db\Schema; |
||||
use yii\db\Migration; |
||||
|
||||
class m150101_185401_criar_tabela_noticias extends Migration |
||||
{ |
||||
public function up() |
||||
{ |
||||
} |
||||
|
||||
public function down() |
||||
{ |
||||
echo "m101129_185401_criar_tabela_noticias cannot be reverted.\n"; |
||||
return false; |
||||
} |
||||
} |
||||
``` |
||||
Cada migração de dados é definida como uma classe PHP extendida de [[yii\db\Migration]]. O nome da |
||||
classe de migração é automaticamente gerado no formato `m<YYMMDD_HHMMSS>_<Nome>`, onde |
||||
|
||||
* `<YYMMDD_HHMMSS>` refere-se a data UTC em que o comando de criação da migração foi executado. |
||||
* `<Nome>` é igual ao valor do argumento `nome` que você passou no comando. |
||||
|
||||
Na classe de migração, é esperado que você escreva no método `up()` as mudanças a serem feitas na estrutura do banco de dados. |
||||
Você também pode escrever código no método `down()` para reverter as mudanças feitas por `up()`. O método `up()` é invocado quando você atualiza o seu banco de dados com esta migração, enquanto o método `down()` é invocado quando você reverte as mudanças no banco. O seguinte código mostra como você pode implementar a classe de migração para criar a tabela `noticias`: |
||||
|
||||
```php |
||||
|
||||
use yii\db\Schema; |
||||
use yii\db\Migration; |
||||
|
||||
class m150101_185401_criar_tabela_noticias extends \yii\db\Migration |
||||
{ |
||||
public function up() |
||||
{ |
||||
$this->createTable('noticias', [ |
||||
'id' => Schema::TYPE_PK, |
||||
'titulo' => Schema::TYPE_STRING . ' NOT NULL', |
||||
'conteudo' => Schema::TYPE_TEXT, |
||||
]); |
||||
} |
||||
|
||||
public function down() |
||||
{ |
||||
$this->dropTable('noticias'); |
||||
} |
||||
|
||||
} |
||||
``` |
||||
|
||||
> Observação: Nem todas as migrações são reversíveis. Por exemplo, se o método `up()` deleta um registro de uma tabela, |
||||
você possívelmente não será capaz de recuperar este registro com o método `down()`. Em alguns casos, você pode ter |
||||
tido muita preguiça e não ter implementado o método `down()`, porque não é muito comum reverter migrações de dados. |
||||
Neste caso, você deve retornar `false` no método `down()` para indicar que a migração não é reversível. |
||||
|
||||
A classe base de Migração [[yii\db\Migration]] expõe a conexão ao banco através da propriedade [[yii\db\Migration::db|db]]. |
||||
Você pode usá-la para manípular o esquema do banco de dados usando os métodos como descritos em |
||||
[Trabalhando com um Esquema de Banco de Dados](db-dao.md#working-with-database-schema-). |
||||
|
||||
Ao invés de usar típos físicos, ao criar uma tabela ou coluna, você deve usar *tipos abstratos* para que |
||||
suas migrações sejam independentes do SGBD. A classe [[yii\db\Schema]] define uma gama de constantes para |
||||
representar os tipos abstratos suportados. Estas constantes são nomeadas no formato `TYPE_<NOME>`. Por exemplo, |
||||
`TYPE_PK` refere-se ao tipo chave primária auto-incrementavel; `TYPE_STRING` refere-se ao típo string. |
||||
Quando a migração for aplicada a um banco de dados em particular, os tipos abstratos serão traduzidos nos |
||||
respectívos tipos físicos. No caso do MySQL, `TYPE_PK` será traduzida para |
||||
`int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY`, enquanto `TYPE_STRING` será `varchar(255)`. |
||||
|
||||
Você pode adicionar algumas constraints ao usar tipos abstratos. No exemplo acíma, ` NOT NULL` é adicionado |
||||
a `Schema::TYPE_STRING` para especificar que a coluna não pode ser nula. |
||||
|
||||
> Observação: O mapeamento entre tipos abstratos e tipos físicos é especificado pela propriedade [[yii\db\QueryBuilder::$typeMap|$typeMap]] em cada classe `QueryBuilder`. |
||||
|
||||
|
||||
### Migrações Transacionais <span id="transactional-migrations"></span> |
||||
|
||||
Ao realizar migrações de dados complexas, é importante assegurar que cada migração irá ter sucesso ou irá falhar |
||||
por completo para que o banco não perca sua integridade e consistencia. Para atingir este objetivo, recomenda-se que |
||||
você encapsule suas operações de banco de dados de cada migração em uma [transação](db-dao.md#performing-transactions-). |
||||
|
||||
Um jeito mais fácil de implementar uma migração transacional é colocar o seu código de migração nos métodos `safeUp()` e `safeDown()`. Estes métodos diferem de `up()` e `down()` por que eles estão implicitamente encapsulados em uma transação. Como resultado, se qualquer operação nestes métodos falhar, todas as operações anteriores sofrerão roll back |
||||
automaticamente. |
||||
|
||||
No exemplo a seguir, além de criar a tabela `noticias` nós também inserimos um registro inicial a esta tabela. |
||||
|
||||
```php |
||||
|
||||
use yii\db\Schema; |
||||
use yii\db\Migration; |
||||
|
||||
class m150101_185401_criar_tabela_noticias extends Migration |
||||
{ |
||||
public function safeUp() |
||||
{ |
||||
$this->createTable('noticias', [ |
||||
'id' => 'pk', |
||||
'titulo' => Schema::TYPE_STRING . ' NOT NULL', |
||||
'conteudo' => Schema::TYPE_TEXT, |
||||
]); |
||||
|
||||
$this->insert('noticias', [ |
||||
'titulo' => 'título 1', |
||||
'conteudo' => 'conteúdo 1', |
||||
]); |
||||
} |
||||
|
||||
public function safeDown() |
||||
{ |
||||
$this->delete('noticias', ['id' => 1]); |
||||
$this->dropTable('noticias'); |
||||
} |
||||
} |
||||
``` |
||||
|
||||
Note que normalmente quando você realiza multiplas operações em `safeUp()`, você deverá reverter a ordem de execução |
||||
em `safeDown()`. No exemplo acima nós primeiramente criamos a tabela e depois inserimos uma túpla em `safeUp()`; enquanto |
||||
em `safeDown()` nós primeiramente apagamos o registro e depois eliminamos a tabela. |
||||
|
||||
> Nota: Nem todos os SGBDs suportam transações. E algumas requisições de banco não podem ser encapsuladas em uma transação. Para alguns exemplos, referir a [commit implicito(inglês)](http://dev.mysql.com/doc/refman/5.1/en/implicit-commit.html). Se este for o caso, implemente os métodos `up()` e `down()`. |
||||
|
||||
### Métodos de acesso ao Banco de Dados <span id="db-accessing-methods"></span> |
||||
|
||||
A classe base migração [[yii\db\Migration]] entrega vários métodos que facilitam o acesso e a manipulação de |
||||
bancos de dados. Você deve achar que estes métodos são nomeados similarmente a [métodos DAO](db-dao.md) encontrados |
||||
na classe [[yii\db\Command]]. Por exemplo, o método [[yii\db\Migration::createTable()]] permite que você crie uma |
||||
nova tabela assim como [[yii\db\Command::createTable()]] o faz. |
||||
|
||||
O benefício ao usar os métodos encontrados em [[yii\db\Migration]] é que você não precisa criar explícitamente |
||||
instancias de [[yii\db\Command]] e a execução de cada método automaticamente exibirá mensagens úteis que dirão |
||||
a você quais operações estão sendo feitas e quanto tempo elas estão durando. |
||||
|
||||
Abaixo está uma lista de todos estes métodos de acesso ao banco de dados: |
||||
|
||||
* [[yii\db\Migration::execute()|execute()]]: executando um SQL |
||||
* [[yii\db\Migration::insert()|insert()]]: inserindo um novo regístro |
||||
* [[yii\db\Migration::batchInsert()|batchInsert()]]: inserindo vários registros |
||||
* [[yii\db\Migration::update()|update()]]: atualizando registros |
||||
* [[yii\db\Migration::delete()|delete()]]: apagando registros |
||||
* [[yii\db\Migration::createTable()|createTable()]]: criando uma tabela |
||||
* [[yii\db\Migration::renameTable()|renameTable()]]: renomeando uma tabela |
||||
* [[yii\db\Migration::dropTable()|dropTable()]]: removendo uma tabela |
||||
* [[yii\db\Migration::truncateTable()|truncateTable()]]: removendo todos os registros em uma tabela |
||||
* [[yii\db\Migration::addColumn()|addColumn()]]: adicionando uma coluna |
||||
* [[yii\db\Migration::renameColumn()|renameColumn()]]: renomeando uma coluna |
||||
* [[yii\db\Migration::dropColumn()|dropColumn()]]: removendo uma coluna |
||||
* [[yii\db\Migration::alterColumn()|alterColumn()]]: alterando uma coluna |
||||
* [[yii\db\Migration::addPrimaryKey()|addPrimaryKey()]]: adicionando uma chave primária |
||||
* [[yii\db\Migration::dropPrimaryKey()|dropPrimaryKey()]]: removendo uma chave primária |
||||
* [[yii\db\Migration::addForeignKey()|addForeignKey()]]: adicionando uma chave estrangeira |
||||
* [[yii\db\Migration::dropForeignKey()|dropForeignKey()]]: removendo uma chave estrangeira |
||||
* [[yii\db\Migration::createIndex()|createIndex()]]: criando um índice |
||||
* [[yii\db\Migration::dropIndex()|dropIndex()]]: removendo um índice |
||||
|
||||
> Observação: [[yii\db\Migration]] não possui um método de consulta ao banco de dados. Isto porque você normalmente não irá precisar exibir informações extras ao recuperar informações de um banco de dados. E além disso você pode usar o poderoso [Query Builder](db-query-builder.md) para construir e executar consultas complexas. |
||||
|
||||
|
||||
## Aplicando migrações <span id="applying-migrations"></span> |
||||
|
||||
Para atualizar um banco de dados para a sua estrutura mais atual, você deve aplicar todas as migracões disponíveis usando o seguinte comando: |
||||
|
||||
``` |
||||
yii migrate |
||||
``` |
||||
|
||||
Este comando irá listar todas as migrações que não foram alicadas até agora. Se você confirmar que deseja aplicar |
||||
estas migrações, cada nova classe de migração irá executar os métodos `up()` ou `safeUp()` um após o outro, na |
||||
ordem relacionada à data marcada em seus nomes. Se qualquer uma das migrações falhar, o comando terminará sem aplicar |
||||
o resto das migrações. |
||||
|
||||
Para cada migração aplicada com sucesso, o comando irá inserir um registro numa tabela no banco de dados chamada |
||||
`migration` para registrar uma aplicação de migração. Isto irá permitir que a ferramenta de migração identifique |
||||
quais migrações foram aplicadas e quais não foram. |
||||
|
||||
> Observação: Esta ferramenta de migração irá automaticamente criar a tabela `migration` no banco de dados especificado pela opção do comando [[yii\console\controllers\MigrateController::db|db]]. Por padrão, o banco de dados é especificado por `db` em [Componentes de Aplicação](structure-application-components.md). |
||||
|
||||
Eventualmente, você desejará aplicar apenas uma ou algumas migrações, em vez de todas as disponíveis. |
||||
Você pode fazê-lo especificando o número de migrações que deseja aplicar ao executar o comando. |
||||
Por exemplo, o comando a seguir irá tentar aplicar as próximas 3 migrações disponíveis: |
||||
|
||||
``` |
||||
yii migrate 3 |
||||
``` |
||||
Você também pode especificar para qual migração em particular o banco de dados deve ser migrado |
||||
usando o comando `migrate/to` em um dos formatos seguintes: |
||||
|
||||
``` |
||||
yii migrate/to 150101_185401 # usando a marcação de data para especificar a migração |
||||
yii migrate/to "2015-01-01 18:54:01" # usando uma string que pode ser analisada por strtotime() |
||||
yii migrate/to m150101_185401_criar_tabela_noticias # usando o nome completo |
||||
yii migrate/to 1392853618 # usando uma marcação de data no estilo UNIX |
||||
``` |
||||
Se existirem migrações mais recentes do que a especificada, elas serão todas aplicadas antes da migração definida. |
||||
|
||||
Se a migração especificada ja tiver sido aplicada, qualquer migração posterior já aplicada será revertida. |
||||
|
||||
|
||||
## Revertendo Migrações <span id="reverting-migrations"></span> |
||||
|
||||
Para reverter uma ou multiplas migrações que tenham sido aplicadas antes, você pode executar o seguinte comando: |
||||
|
||||
``` |
||||
yii migrate/down # reverter a última migração aplicada |
||||
yii migrate/down 3 # reverter as 3 últimas migrações aplicadas |
||||
``` |
||||
|
||||
> Nota: Nem todas as migrações são reversíveis. Tentar reverter tais migrações irá causar um erro que irá cancelar todo o processo de reversão. |
||||
|
||||
|
||||
## Refazendo Migrações <span id="redoing-migrations"></span> |
||||
|
||||
Refazer as migrações significa primeiramente reverter migrações especificadas e depois aplicá-las novamente. |
||||
Isto pode ser feito da seguinte maneira: |
||||
|
||||
``` |
||||
yii migrate/redo # refazer a última migração aplicada |
||||
yii migrate/redo 3 # refazer as 3 últimas migrações aplicadas |
||||
``` |
||||
|
||||
> Nota: Se a migração não for reversível, você não poderá refazê-la. |
||||
|
||||
|
||||
## Listando Migrações <span id="listing-migrations"></span> |
||||
|
||||
Para listar quais migrações foram aplicadas e quais não foram, você deve usar os seguintes comandos: |
||||
|
||||
``` |
||||
yii migrate/history # exibir as 10 últimas migrações aplicadas |
||||
yii migrate/history 5 # exibir as 5 últimas migrações aplicadas |
||||
yii migrate/history all # exibir todas as migrações aplicadas |
||||
|
||||
yii migrate/new # exibir as 10 primeiras novas migrações |
||||
yii migrate/new 5 # exibir as 5 primeiras novas migrações |
||||
yii migrate/new all # exibir todas as novas migrações |
||||
``` |
||||
|
||||
|
||||
## Modificando o Histórico das Migrações <span id="modifying-migration-history"></span> |
||||
|
||||
Ao invés de aplicar ou reverter migrações, pode ser que você queira apenas definir que o seu banco de dados |
||||
foi atualizado para uma migração em particular. Isto normalmente acontece quando você muda manualmente o banco |
||||
de dados para um estado em particular, e não deseja que as mudanças para aquela migração sejam reaplicadas |
||||
posteriormente. Você pode alcancar este objetivo com o seguinte comando: |
||||
|
||||
``` |
||||
yii migrate/mark 150101_185401 # usando a marcação de data para especificar a migração |
||||
yii migrate/mark "2015-01-01 18:54:01" # usando uma string que pode ser analisada por strtotime() |
||||
yii migrate/mark m150101_185401_criar_tabela_noticias # usando o nome completo |
||||
yii migrate/mark 1392853618 # usando uma marcação de data no estilo UNIX |
||||
``` |
||||
O comando irá modificar a tabela `migration` adicionando ou deletando certos registros para indicar que o banco |
||||
de dados sofreu as migrações especificadas. Nenhuma migração será aplicada ou revertida por este comando. |
||||
|
||||
|
||||
## Customizando Migrações <span id="customizing-migrations"></span> |
||||
|
||||
Existem várias maneiras de customizar o comando de migração. |
||||
|
||||
|
||||
### Usando Opções na Linha de Comando <span id="using-command-line-options"></span> |
||||
|
||||
O comando de migração vem com algumas opções de linha de comando que podem ser usadas para customizar o seu comportamento: |
||||
|
||||
* `interactive`: boolean (o padrão é true), especifica se as migrações serão executadas em modo interativo. |
||||
Quando for true, ao usuario será perguntado se a execução deve continuar antes de o comando executar certas ações. |
||||
Você provavelmente marcará isto para falso se o comando estiver sendo feito em algum processo em segundo plano. |
||||
|
||||
* `migrationPath`: string (o padrão é `@app/migrations`), especifica o diretório em que os arquivos das classes de migração estão. Isto pode ser especificado ou como um diretório ou como um [alias](concept-aliases.md). |
||||
Note que o diretório deve existir, ou o comando irá disparar um erro. |
||||
|
||||
* `migrationTable`: string (o padrão é `migration`), especifica o nome da tabela no banco de dados para armazenar o histórico das migrações. A tabela será automaticamente criada pelo comando caso não exista. |
||||
Você também pode criá-la manualmente usando a estrutura `version varchar(255) primary key, apply_time integer`. |
||||
|
||||
* `db`: string (o padrão é `db`), especifica o banco de dados [componente de aplicação](structure-application-components.md). |
||||
Representa qual banco sofrerá as migrações usando este comando. |
||||
|
||||
* `templateFile`: string (o padrão é `@yii/views/migration.php`), especifica o caminho do arquivo de modelo que é usado para gerar um esqueleto para os arquivos das classes de migração. Isto pode ser especificado por um caminho de arquivo ou por um [alias](concept-aliases.md). O arquivo modelo é um script PHP em que você pode usar uma variaval pré-definida `$className` para obter o nome da classe de migração. |
||||
|
||||
O seguinte exemplo exibe como você pode usar estas opções. |
||||
|
||||
Por exemplo, se nós quisermos migrar um módulo `forum` cujo os arquivos de migração estão localizados dentro da pasta `migrations` do módulo, nós podemos usar o seguinte comando: |
||||
|
||||
``` |
||||
# migrate the migrations in a forum module non-interactively |
||||
yii migrate --migrationPath=@app/modules/forum/migrations --interactive=0 |
||||
``` |
||||
|
||||
|
||||
### Configurando o Comando Globalmente <span id="configuring-command-globally"></span> |
||||
|
||||
Ao invés de fornecer opções todas as vezes que você executar o comando de migração, |
||||
você pode configurá-lo de uma vez por todas na configuração da aplicação como exibido abaixo: |
||||
|
||||
```php |
||||
return [ |
||||
'controllerMap' => [ |
||||
'migrate' => [ |
||||
'class' => 'yii\console\controllers\MigrateController', |
||||
'migrationTable' => 'backend_migration', |
||||
], |
||||
], |
||||
]; |
||||
``` |
||||
|
||||
Com a configuração acima, toda a vez que você executar o comando de migração, a tabela `backend_migration` |
||||
será usada para gravar o histórico de migração. Você não irá mais precisar fornecê-la através da opção `migrationTable`. |
||||
|
||||
|
||||
## Migrando Multiplos Bancos De Dados <span id="migrating-multiple-databases"></span> |
||||
|
||||
Por padrão, as migrações são aplicadas no mesmo banco de dados especificado por `db` [componente de aplicação](structure-application-components.md). |
||||
Se você quiser que elas sejam aplicadas em um banco de dados diferente, você deve especificar na opção `db` como exibido abaixo, |
||||
|
||||
``` |
||||
yii migrate --db=db2 |
||||
``` |
||||
|
||||
O comando acima irá aplicar as migrações para o banco de dados `db2`. |
||||
|
||||
Algumas vezes pode ocorrer que você queira aplicar *algumas* das migrações para um banco de dados, e outras para |
||||
outro banco de dados. Para atingir este objetivo, ao implementar uma classe de migração você deve especificar a |
||||
ID do componente DB que a migração irá usar, como o seguinte: |
||||
|
||||
```php |
||||
use yii\db\Schema; |
||||
use yii\db\Migration; |
||||
|
||||
class m150101_185401_criar_tabela_noticias extends Migration |
||||
{ |
||||
public function init() |
||||
{ |
||||
$this->db = 'db2'; |
||||
parent::init(); |
||||
} |
||||
} |
||||
``` |
||||
|
||||
A migração acima será aplicada a `db2`, mesmo que você especifique um banco de dados diferente através da opção `db`. Note que o histórico da migração continuará sendo registrado no banco especificado pela opção `db`. |
||||
Se você tiver multiplas migrações que usam o mesmo banco de dados, é recomenda-se criar uma classe de migração |
||||
base com o codigo acima em `init()`. Então cada classe de migração poderá ser extendida desta classe base. |
||||
|
||||
> Dica: Apesas de definir a propriedade [[yii\db\Migration::db|db]], você também pode operar em diferentes bancos |
||||
de dados ao criar novas conexões de banco para eles em sua classe de migração. Você então usará os [métodos DAO](db-dao.md) |
||||
com estas conexões para manipular diferentes bancos de dados. |
||||
|
||||
Outra estratégia que você pode seguir para migrar multiplos bancos de dados é manter as migrações para diferentes bancos |
||||
de dados em diferentes pastas de migrações. Então você poderá migrar estes bancos de dados em comandos separados como os seguintes: |
||||
|
||||
``` |
||||
yii migrate --migrationPath=@app/migrations/db1 --db=db1 |
||||
yii migrate --migrationPath=@app/migrations/db2 --db=db2 |
||||
... |
||||
``` |
||||
|
||||
O primeiro comando irá aplicar as migrações em `@app/migrations/db1` para o banco de dados `db1`, e o segundo comando |
||||
irá aplicar as migrações em `@app/migrations/db2` para `db2`, e assim sucessivamente. |
@ -0,0 +1,162 @@
|
||||
Requisições |
||||
=========== |
||||
|
||||
As requisições realizadas na aplicação são representadas pelo objeto [[yii\web\Request]] |
||||
que fornece informações como os parâmetros da requisição, cabeçalhos HTTP, cookies |
||||
e etc. Em uma determinada requisição, você pode acessar o objeto da requisição |
||||
correspondente através do [componente da aplicação](structure-application-components.md) |
||||
`request`, que é uma instância de [[yii\web\Request]], por padrão. Nesta seção, |
||||
descreveremos como você pode usar este componente em sua aplicação. |
||||
|
||||
|
||||
## Parâmetros da Requisição <span id="request-parameters"></span> |
||||
|
||||
Para obter os parâmetros da requisição, você pode chamar os métodos |
||||
[[yii\web\Request::get()|get()]] e [[yii\web\Request::post()|post()]] do |
||||
componente `request`. Estes métodos retornam os valores de `$_GET` e `$_POST`, |
||||
respectivamente. Por exemplo, |
||||
|
||||
```php |
||||
$request = Yii::$app->request; |
||||
|
||||
$get = $request->get(); |
||||
// equivalente à: $get = $_GET; |
||||
|
||||
$id = $request->get('id'); |
||||
// equivalente à: $id = isset($_GET['id']) ? $_GET['id'] : null; |
||||
|
||||
$id = $request->get('id', 1); |
||||
// equivalente à: $id = isset($_GET['id']) ? $_GET['id'] : 1; |
||||
|
||||
$post = $request->post(); |
||||
// equivalente à: $post = $_POST; |
||||
|
||||
$name = $request->post('name'); |
||||
// equivalente à: $name = isset($_POST['name']) ? $_POST['name'] : null; |
||||
|
||||
$name = $request->post('name', ''); |
||||
// equivalente à: $name = isset($_POST['name']) ? $_POST['name'] : ''; |
||||
``` |
||||
|
||||
> Informação: Ao invés de acessar diretamente o `$_GET` e o `$_POST` para recuperar |
||||
os parâmetros da requisição, é recomendável que os utilizem através do componente |
||||
`request`, como mostrado nos exemplos acima. Isto permite que você escreva testes |
||||
de forma mais simples, utilizando um componente da requisição que retornem valores |
||||
pré-determinados. |
||||
|
||||
Ao implementar o [RESTful APIs](rest-quick-start.md), muitas vezes você precisará |
||||
recuperar os parâmetros que foram enviados pelos [métodos de requisição](#request-methods) |
||||
PUT, PATCH ou outro. Você pode recuperá-los chamando o método [[yii\web\Request::getBodyParam()]]. |
||||
Por exemplo, |
||||
|
||||
```php |
||||
$request = Yii::$app->request; |
||||
|
||||
// retorna todos os parâmetros |
||||
$params = $request->bodyParams; |
||||
|
||||
// retorna o parâmetro "id" |
||||
$param = $request->getBodyParam('id'); |
||||
``` |
||||
|
||||
> Informação: Tirando os parâmetros `GET`, os parâmetros `POST`, `PUT`, `PATCH` |
||||
e etc são enviados no corpo da requisição. O componente `request` analisará |
||||
estes parâmetros quando você acessá-los através dos métodos descritos acima. |
||||
Você pode personalizar a forma como estes parâmetros são analisados pela |
||||
configuração da propriedade [[yii\web\Request::parsers]]. |
||||
|
||||
|
||||
## Métodos da Requisição <span id="request-methods"></span> |
||||
|
||||
Você pode obter o método HTTP usado pela requisição atual através da expressão |
||||
`Yii::$app->request->method`. Um conjunto de propriedades booleanas também são |
||||
fornecidos para que você consiga verificar se o método atual é o correto. |
||||
Por exemplo, |
||||
|
||||
```php |
||||
$request = Yii::$app->request; |
||||
|
||||
if ($request->isAjax) { /* a requisição é uma requisição Ajax */ } |
||||
if ($request->isGet) { /* o método da requisição é GET */ } |
||||
if ($request->isPost) { /* o método da requisição é POST */ } |
||||
if ($request->isPut) { /* o método da requisição é PUT */ } |
||||
``` |
||||
|
||||
## URLs da Requisição <span id="request-urls"></span> |
||||
|
||||
O componente `request` fornece muitas formas de inspecionar a atual URL da requisição. |
||||
Assumindo que a URL da requisição seja `http://example.com/admin/index.php/product?id=100`, |
||||
você pode obter várias partes desta URL através das propriedades explicadas a seguir: |
||||
|
||||
* [[yii\web\Request::url|url]]: retorna `/admin/index.php/product?id=100`, que é |
||||
a URL sem as informações de protocolo e de domínio. |
||||
* [[yii\web\Request::absoluteUrl|absoluteUrl]]: retorna `http://example.com/admin/index.php/product?id=100`, |
||||
que é a URL completa, incluindo as informações de protocolo e de domínio. |
||||
* [[yii\web\Request::hostInfo|hostInfo]]: retorna `http://example.com`, que são |
||||
as informações de protocolo e de domínio da URL. |
||||
* [[yii\web\Request::pathInfo|pathInfo]]: retorna `/product`, que é a informação |
||||
depois do script de entrada e antes da interrogação (da query string). |
||||
* [[yii\web\Request::queryString|queryString]]: retorna `id=100`, que é a |
||||
informação depois da interrogação. |
||||
* [[yii\web\Request::baseUrl|baseUrl]]: retorna `/admin`, que é a informação |
||||
depois do domínio e antes do script de entrada. |
||||
* [[yii\web\Request::scriptUrl|scriptUrl]]: retorna `/admin/index.php`, que é a |
||||
informação depois do domínio até o script de entrada, inclusive. |
||||
* [[yii\web\Request::serverName|serverName]]: retorna `example.com`, que é o |
||||
domínio da URL. |
||||
* [[yii\web\Request::serverPort|serverPort]]: retorna 80, que é a porta usada |
||||
pelo servidor Web. |
||||
|
||||
|
||||
## Cabeçalho HTTP <span id="http-headers"></span> |
||||
|
||||
Você pode obter as informações do cabeçalho HTTP através da |
||||
[[yii\web\HeaderCollection|coleção de cabeçalho]] retornado pela propriedade |
||||
[[yii\web\Request::headers]]. Por exemplo, |
||||
|
||||
```php |
||||
// $headers é um objeto de yii\web\HeaderCollection |
||||
$headers = Yii::$app->request->headers; |
||||
|
||||
// retorna o valor do cabeçalho Accept |
||||
$accept = $headers->get('Accept'); |
||||
|
||||
if ($headers->has('User-Agent')) { /* existe o cabeçalho User-Agent */ } |
||||
``` |
||||
|
||||
O componente `request` também fornece suporte para fácil acesso de alguns |
||||
cabeçalhos mais utilizados, incluindo: |
||||
|
||||
* [[yii\web\Request::userAgent|userAgent]]: retorna o valor do cabeçalho `User-Agent`. |
||||
* [[yii\web\Request::contentType|contentType]]: retorna o valor do cabeçalho |
||||
`Content-Type` que indica o tipo MIME dos dados do corpo da requisição. |
||||
* [[yii\web\Request::acceptableContentTypes|acceptableContentTypes]]: retorna os |
||||
tipos MIME acessíveis pelos usuários. Os tipos retornados são ordenados pela |
||||
sua pontuação de qualidade. Tipos com mais pontuação aparecerão nas primeiras posições. |
||||
* [[yii\web\Request::acceptableLanguages|acceptableLanguages]]: retorna os idiomas |
||||
acessíveis pelos usuários. Os idiomas retornados são ordenados pelo nível de |
||||
preferência. O primeiro elemento representa o idioma de maior preferência. |
||||
|
||||
Se a sua aplicação suportar diversos idiomas e quiser exibir páginas no idioma |
||||
de maior preferência do usuário, você pode usar o método de negociação |
||||
[[yii\web\Request::getPreferredLanguage()]]. Este método pega uma lista de |
||||
idiomas suportadas pela sua aplicação e compara com |
||||
[[yii\web\Request::acceptableLanguages|acceptableLanguages]], para retornar o |
||||
idioma mais adequado. |
||||
|
||||
> Dica: Você também pode utilizar o filtro [[yii\filters\ContentNegotiator|ContentNegotiator]] |
||||
para determinar dinamicamente qual tipo de conteúdo e idioma que deve ser utilizado |
||||
na resposta. O filtro implementa negociação de conteúdo em cima das propriedades |
||||
e métodos descritos acima. |
||||
|
||||
|
||||
## Informações do Cliente <span id="client-information"></span> |
||||
|
||||
Você pode obter o nome do domínio ou endereço IP da máquina do cliente através |
||||
das propriedades [[yii\web\Request::userHost|userHost]] e |
||||
[[yii\web\Request::userIP|userIP]], respectivamente. Por exemplo, |
||||
|
||||
```php |
||||
$userHost = Yii::$app->request->userHost; |
||||
$userIP = Yii::$app->request->userIP; |
||||
``` |
@ -0,0 +1,752 @@
|
||||
Roteamento e Criação de URL |
||||
=========================== |
||||
|
||||
Quando uma aplicação Yii começa a processar uma URL requerida, o primeiro passo |
||||
necessário é obter a rota pela análise da URL. A rota é usada para instanciar o |
||||
[controlador (controller) da ação](structure-controllers.md) correspondente para |
||||
manipular a requisição. Todo este processo é chamado de *roteamento*. |
||||
|
||||
O processo inverso do roteamento é chamada de *criação de URL*, onde é criado uma |
||||
URL a partir de uma determinada rota e seus parâmetros. Quando a URL criada for |
||||
exigida em outro momento, o processo de roteamento pode resolve-la de volta para |
||||
a rota original e seus parâmetros. |
||||
|
||||
O ponto central responsável pelo roteamento e pela criação de URL é o |
||||
[[yii\web\UrlManager|gerenciador de URL]], na qual é registrado como o |
||||
[componente da aplicação](structure-application-components.md) `urlManager`. O |
||||
[[yii\web\UrlManager|gerenciador de URL]] fornece o método |
||||
[[yii\web\UrlManager::parseRequest()|parseRequest()]] para analisar um requisição |
||||
de entrada a fim de obter uma rota e seus parâmetros associados; e o método |
||||
[[yii\web\UrlManager::createUrl()|createUrl()]] para criar uma URL a partir de |
||||
uma rota e seus parâmetros associados. |
||||
|
||||
Ao configurar o componente `urlManager` na configuração da aplicação, poderá |
||||
fazer com que sua aplicação reconheça de forma arbitrária diversos formatos de |
||||
URL sem modificar o código existente da aplicação. Por exemplo, você pode usar o |
||||
código a seguir para criar uma URL a partir da ação `post/view`: |
||||
|
||||
```php |
||||
use yii\helpers\Url; |
||||
|
||||
// Url::to() chama UrlManager::createUrl() para criar uma URL |
||||
$url = Url::to(['post/view', 'id' => 100]); |
||||
``` |
||||
|
||||
Dependendo da configuração da propriedade `urlManager`, a URL criada pode ser |
||||
parecida com um dos formatos a seguir (ou até mesmo com outro formato). E se a |
||||
URL criada for requerida, ainda será analisada a fim de obter a rota e os valores |
||||
dos parâmetros originais. |
||||
|
||||
``` |
||||
/index.php?r=post/view&id=100 |
||||
/index.php/post/100 |
||||
/posts/100 |
||||
``` |
||||
|
||||
|
||||
## Formatos de URL <span id="url-formats"></span> |
||||
|
||||
O [[yii\web\UrlManager|gerenciador de URL]] suporta dois formatos de URL: o |
||||
formato de URL padrão e o formato de URL amigável (pretty URL). |
||||
|
||||
O formato de URL padrão usa um parâmetro chamado `r` para representar a rota e |
||||
os demais parâmetros representam os parâmetros associados a rota. Por exemplo, a |
||||
URL `/index.php?r=post/view&id=100` representa a rota `post/view` e o parâmetro |
||||
`id` com o valor 100. O formato de URL padrão não exige qualquer tipo de |
||||
configuração no [[yii\web\UrlManager|gerenciador de URL]] e trabalha em qualquer |
||||
servidor Web. |
||||
|
||||
O formato de URL amigável (pretty URL) usa um caminho adicional após o nome do |
||||
script de entrada para representar a rota e seus parâmetros. Por exemplo, o |
||||
caminho adicional na URL `/index.php/post/100` é `/post/100`, onde pode |
||||
representar, em uma adequada [[yii\web\UrlManager::rules|regra de URL]], a rota |
||||
`post/view` e o parâmetro `id` com o valor 100. Para usar o formato de URL |
||||
amigável (pretty URL), você precisará escrever um conjunto de |
||||
[[yii\web\UrlManager::rules|regras de URLs]] de acordo com a necessidade sobre |
||||
como as URLs devem parecer. |
||||
|
||||
Você pode alterar entre os dois formatos de URLs, alternando a propriedade |
||||
[[yii\web\UrlManager::enablePrettyUrl|enablePrettyUrl]] do |
||||
[[yii\web\UrlManager|gerenciador de URL]] sem alterar qualquer código na aplicação. |
||||
|
||||
|
||||
## Roteamento <span id="routing"></span> |
||||
|
||||
O roteamento envolve duas etapas. Na primeira etapa, a requisição de entrada é |
||||
transformada em uma rota e seus parâmetros. Na segunda etapa, a |
||||
[ação do controller (controlador)](structure-controllers.md) correspondente a |
||||
rota analisada será criada para processar a requisição. |
||||
|
||||
Ao utilizar o formato de URL padrão, a análise de uma requisição para obter uma |
||||
rota é tão simples como pegar o valor via `GET` do parâmetro `r`. |
||||
|
||||
Ao utilizar o formato de URL amigável (pretty URL), o |
||||
[[yii\web\UrlManager|gerenciado de URL]] examinará as |
||||
[[yii\web\UrlManager::rules|regras de URLs]] registradas para encontrar alguma |
||||
correspondência que poderá resolver a requisição em uma rota. Se tal regra não |
||||
for encontrada, uma exceção [[yii\web\NotFoundHttpException]] será lançada. |
||||
|
||||
Uma vez que a requisição analisada apresentar uma rota, é hora de criar a ação |
||||
do controller (controlador) identificado pela rota. |
||||
A rota é dividida em várias partes pelo separador barra (“/”). Por exemplo, a |
||||
rota `site/index` será dividida em duas partes: `site` e `index`. Cada parte é |
||||
um ID que pode referenciar a um módulo, um controller (controlador) ou uma ação. |
||||
A partir da primeira parte da rota, a aplicação executará as seguintes etapas para |
||||
criar o módulo (se existir), o controller (controlador) e a ação: |
||||
|
||||
1. Define a aplicação como o módulo atual. |
||||
2. Verifica se o [[yii\base\Module::controllerMap|mapa do controller (controlador)]] |
||||
do módulo contém o ID atual. Caso exista, um objeto do controller (controlador) |
||||
será criado de acordo com a configuração do controller (controlador) encontrado |
||||
no mapa e a etapa 3 e 4 não serão executadas. |
||||
3. Verifica se o ID referência a um módulo listado na propriedade |
||||
[[yii\base\Module::modules|modules]] do módulo atual. Caso exista, um módulo |
||||
será criado de acordo com as configurações encontradas na lista e a etapa 2 |
||||
será executada como etapa seguinte do processo, no âmbito de usar o contexto |
||||
do módulo recém-criado. |
||||
4. Trata o ID como um ID do controller (controlador) e cria um objeto do controller |
||||
(controlador). Siga para a próxima etapa, como parte restante do processo. |
||||
5. O controller (controlador) procura o ID atual em seu |
||||
[[yii\base\Controller::actions()|mapa de ações]]. Caso exista, será criado uma |
||||
ação de acordo com a configuração encontrada no mapa. Caso contrário, o |
||||
controller (controlador) tentará criar uma ação inline que é definida por um |
||||
método da ação correspondente ao ID atual. |
||||
|
||||
Nas etapas acima, se ocorrer qualquer erro, uma exceção [[yii\web\NotFoundHttpException]] |
||||
será lançada, indicando a falha no processo de roteamento. |
||||
|
||||
|
||||
### Rota Padrão <span id="default-route"></span> |
||||
|
||||
Quando uma requisição analisada apresentar uma rota vazia, a assim chamada |
||||
*rota padrão* será usada em seu lugar. A rota padrão é `site/index` é utilizada |
||||
como padrão, que referencia a ação `index` do controller (controlador) `site`. |
||||
Você pode personalizar esta configuração pela propriedade |
||||
[[yii\web\Application::defaultRoute|defaultRoute]] na configuração da aplicação |
||||
como mostrado a seguir: |
||||
|
||||
```php |
||||
[ |
||||
// ... |
||||
'defaultRoute' => 'main/index', |
||||
]; |
||||
``` |
||||
|
||||
|
||||
### Rota `catchAll` <span id="catchall-route"></span> |
||||
|
||||
Às vezes você pode querer colocar sua aplicação Web em modo de manutenção |
||||
temporariamente e exibir uma mesma página com informações para todas as requisições. |
||||
Existem muitas maneiras de atingir este objetivo. Mas uma das maneiras mais simples |
||||
é apenas configurar a propriedade [[yii\web\Application::catchAll]] na configuração |
||||
da aplicação como mostrado a seguir: |
||||
|
||||
```php |
||||
[ |
||||
// ... |
||||
'catchAll' => ['site/offline'], |
||||
]; |
||||
``` |
||||
|
||||
Na configuração acima, a ação `site/offline` será utilizado para lidar com todas |
||||
as requisições recebidas. |
||||
|
||||
A propriedade `catchAll` deve receber um array, o primeiro elemento especifica a |
||||
rota e o restante dos elementos (pares de nomes e seus valores) especificam os |
||||
parâmetros a serem [associados a ação](structure-controllers.md#action-parameters). |
||||
|
||||
|
||||
## Criando URLs <span id="creating-urls"></span> |
||||
|
||||
O Yii fornece um método de ajuda [[yii\helpers\Url::to()]] para criar vários tipos |
||||
de URLs a partir de determinadas rotas e seus parâmetros. Por exemplo, |
||||
|
||||
```php |
||||
use yii\helpers\Url; |
||||
|
||||
// cria uma URL para uma rota: /index.php?r=post/index |
||||
echo Url::to(['post/index']); |
||||
|
||||
// cria uma URL para uma rota com parâmetros: /index.php?r=post/view&id=100 |
||||
echo Url::to(['post/view', 'id' => 100]); |
||||
|
||||
// cria uma URL ancorada: /index.php?r=post/view&id=100#content |
||||
echo Url::to(['post/view', 'id' => 100, '#' => 'content']); |
||||
|
||||
// cria uma URL absoluta: http://www.example.com/index.php?r=post/index |
||||
echo Url::to(['post/index'], true); |
||||
|
||||
// cria uma URL absoluta usando https: https://www.example.com/index.php?r=post/index |
||||
echo Url::to(['post/index'], 'https'); |
||||
``` |
||||
|
||||
Observe que nos exemplos acima, assumimos o formato de URL padrão. Se o formato |
||||
de URL amigável (pretty URL) estiver habilitado, as URLs criadas serão diferentes |
||||
de acordo com as [[yii\web\UrlManager::rules|regra de URL]] em uso. |
||||
|
||||
A rota passada para o método [[yii\helpers\Url::to()]] é sensível ao contexto. |
||||
Ele pode ser tanto uma rota *relativa* quanto uma rota *absoluta* que será |
||||
normalizada de acordo com as regras a seguir: |
||||
|
||||
- Se a rota for uma string vazia, a requisição atual [[yii\web\Controller::route|route]] será usada; |
||||
- Se a rota não contivér barras (“/”), ele será considerado um ID da ação do |
||||
controller (controlador) atual e será antecedido pelo valor da propriedade |
||||
[[\yii\web\Controller::uniqueId|uniqueId]] do controller (controlador) atual; |
||||
- Se a rota não contivér uma barra (“/”) inicial, será considerado como uma rota |
||||
relativa ao módulo atual e será antecedido pelo valor da propriedade |
||||
[[\yii\base\Module::uniqueId|uniqueId]] do módulo atual. |
||||
|
||||
A partir da versão 2.0.2, você pode especificar uma rota usando |
||||
[alias](concept-aliases.md). Se for este o caso, a alias será a primeira a ser |
||||
convertida em uma rota real e em seguida será transformada em uma rota absoluta |
||||
de acordo com as regras informadas anteriormente. |
||||
|
||||
Por exemplo, assumindo que o módulo atual é `admin` e o controller (controlador) |
||||
atual é `post`, |
||||
|
||||
```php |
||||
use yii\helpers\Url; |
||||
|
||||
// rota atual requerida: /index.php?r=admin/post/index |
||||
echo Url::to(['']); |
||||
|
||||
// uma rota relativa com apenas o ID da ação: /index.php?r=admin/post/index |
||||
echo Url::to(['index']); |
||||
|
||||
// uma rota relativa: /index.php?r=admin/post/index |
||||
echo Url::to(['post/index']); |
||||
|
||||
// uma rota absoluta: /index.php?r=post/index |
||||
echo Url::to(['/post/index']); |
||||
|
||||
// /index.php?r=post/index assumindo que a alias "@posts" foi definida como "/post/index" |
||||
echo Url::to(['@posts']); |
||||
``` |
||||
|
||||
O método [[yii\helpers\Url::to()]] é implementado através das chamadas dos métodos |
||||
[[yii\web\UrlManager::createUrl()|createUrl()]] e |
||||
[[yii\web\UrlManager::createAbsoluteUrl()|createAbsoluteUrl()]] do |
||||
[[yii\web\UrlManager|gerenciador de URL]]. |
||||
Nas próximas subseções, iremos explicar como configurar o |
||||
[[yii\web\UrlManager|gerenciador de URL]] para personalizar os formatos das URLs criadas. |
||||
|
||||
O método [[yii\helpers\Url::to()]] também suporta a criação de URLs NÃO relacionadas |
||||
a uma rota em particular. Neste caso, ao invés de passar um array como seu primeiro |
||||
parâmetro, você pode passar uma string. Por exemplo, |
||||
|
||||
```php |
||||
use yii\helpers\Url; |
||||
|
||||
// rota atual requerida: /index.php?r=admin/post/index |
||||
echo Url::to(); |
||||
|
||||
// uma alias da URL: http://example.com |
||||
Yii::setAlias('@example', 'http://example.com/'); |
||||
echo Url::to('@example'); |
||||
|
||||
// uma URL absoluta: http://example.com/images/logo.gif |
||||
echo Url::to('/images/logo.gif', true); |
||||
``` |
||||
|
||||
Além do método `to()`, a classe auxiliar [[yii\helpers\Url]] também fornece uma |
||||
série de métodos referentes a criação de URLs. Por exemplo, |
||||
|
||||
```php |
||||
use yii\helpers\Url; |
||||
|
||||
// URL da página inicial: /index.php?r=site/index |
||||
echo Url::home(); |
||||
|
||||
// URL base, útil se a aplicação for implementada em uma subpasta da pasta raiz do servidor Web |
||||
echo Url::base(); |
||||
|
||||
// A URL canônica da requisição atual |
||||
// Veja mais detalhes em https://en.wikipedia.org/wiki/Canonical_link_element |
||||
echo Url::canonical(); |
||||
|
||||
// Obtêm a URL da requisição anterior para reutilizá-la em requisições futuras |
||||
Url::remember(); |
||||
echo Url::previous(); |
||||
``` |
||||
|
||||
|
||||
## Usando URLs Amigáveis (Pretty URLs) <span id="using-pretty-urls"></span> |
||||
|
||||
Para utilizar as URLs amigáveis (pretty URLs), configure o componente `urlManager` |
||||
na configuração da aplicação conforme o exemplo a seguir: |
||||
|
||||
```php |
||||
[ |
||||
'components' => [ |
||||
'urlManager' => [ |
||||
'enablePrettyUrl' => true, |
||||
'showScriptName' => false, |
||||
'enableStrictParsing' => false, |
||||
'rules' => [ |
||||
// ... |
||||
], |
||||
], |
||||
], |
||||
] |
||||
``` |
||||
|
||||
A propriedade [[yii\web\UrlManager::enablePrettyUrl|enablePrettyUrl]] é obrigatória |
||||
para habilitar o formato de URL amigável (pretty URL). |
||||
O restante das propriedades são opcionais. No entanto, a configuração utilizada |
||||
acima é a mais utilizada. |
||||
|
||||
* [[yii\web\UrlManager::showScriptName|showScriptName]]: esta propriedade determina |
||||
se o script de entrada deve ser incluído ou não nas URLs criadas. Por exemplo, |
||||
ao invés de criar uma URL `/index.php/post/100`, definindo esta propriedade |
||||
como `false`, a URL `/post/100` será gerada. |
||||
* [[yii\web\UrlManager::enableStrictParsing|enableStrictParsing]]: esta propriedade |
||||
habilita uma análise rigorosa (strict parsing) da requisição. Caso a análise |
||||
rigorosa estiver habilitada, a URL da requisição deve corresponder pelo menos |
||||
a uma das regras definidas pela propriedade [[yii\web\UrlManager::rules|rules]] |
||||
a fim de ser tratado como uma requisição válida, caso contrário a exceção |
||||
[[yii\web\NotFoundHttpException]] será lançada. Caso a análise rigorosa estiver |
||||
desabilitada, as regras definidas pela propriedade |
||||
[[yii\web\UrlManager::rules|rules]] NÃO serão verificadas e as informações |
||||
obtidas pela URL serão tratadas como a rota da requisição. |
||||
* [[yii\web\UrlManager::rules|rules]]: esta propriedade contém uma lista de |
||||
regras especificando como serão analisadas e criadas as URLs. Esta é a principal |
||||
propriedade que você deve trabalhar para criar URLs cujos formatos satisfaçam |
||||
a sua exigência em particular. |
||||
|
||||
> Observação: A fim de esconder o nome do script de entrada nas URLs criadas, |
||||
além de definir a propriedade [[yii\web\UrlManager::showScriptName|showScriptName]] |
||||
como `false`, você também pode precisar configurar o seu servidor Web para |
||||
identificar corretamente o script PHP quando uma URL da requisição não |
||||
especificar um explicitamente. Caso você estejam utilizando um servidor Web |
||||
com Apache, você pode consultar a configuração recomendada, conforme descrito |
||||
na seção [Installation](start-installation.md#recommended-apache-configuration). |
||||
|
||||
|
||||
### Regras de URLs <span id="url-rules"></span> |
||||
|
||||
Uma regra de URL é uma instância de [[yii\web\UrlRule]] ou de classes que as estendam. |
||||
Cada regra de URL consiste de um padrão usado para combinar as partes do caminho |
||||
das URLs, como uma rota e alguns parâmetros. Uma regra de URL pode ser usado para |
||||
analisar uma URL da requisição somente se o padrão corresponder com a esta URL. |
||||
Uma regra de URL pode ser usada para criar uma URL para corresponder a uma |
||||
determinada rota e seus parâmetros. |
||||
|
||||
Quando uma formato de URL amigável (pretty URL) estiver habilitada, o |
||||
[[yii\web\UrlManager|gerenciador de URL]] utilizará as regras de URLs declaradas |
||||
na propriedade [[yii\web\UrlManager::rules|rules]] para analisar as requisições |
||||
e para criar URLs. Em particular, para analisar uma requisição, o |
||||
[[yii\web\UrlManager|gerenciador de URL]] verificará as regras na ordem em que |
||||
foram declaradas e só enxergará a *primeira* regra que corresponda a URL da |
||||
requisição. A regra que foi correspondida é então utilizada para obter a rota e |
||||
seus parâmetros a partir de sua análise. A mesma coisa acontece na criação de |
||||
URLs, o [[yii\web\UrlManager|gerenciador de URL]] enxergará apenas a primeira |
||||
regra que corresponda a rota e seus parâmetros para serem utilizados na criação |
||||
de uma URL. |
||||
|
||||
Você pode configurar a propriedade [[yii\web\UrlManager::rules]] com um array |
||||
composto de pares de chave-valor, onde a chave é o padrão da regra e o valor |
||||
serão as rotas. Cada par de padrão-rota define uma regra de URL. Por exemplo, |
||||
as [[yii\web\UrlManager::rules|regras]] a seguir configuram duas regras de URL. |
||||
A primeira regra corresponde a uma URL chamada `posts` sendo mapeado para utilizar |
||||
a rota `post/index`. |
||||
A segunda regra corresponde a uma URL que combine com expressão regular |
||||
`post/(\d+)` seguido de um parâmetro chamado `id` sendo mapeado para utilizar a |
||||
rota `post/view`. |
||||
|
||||
```php |
||||
[ |
||||
'posts' => 'post/index', |
||||
'post/<id:\d+>' => 'post/view', |
||||
] |
||||
``` |
||||
|
||||
> Informação: O padrão em uma regra é usado para identificar o caminho de uma URL. |
||||
Por exemplo, o caminho da URL `/index.php/post/100?source=ad` é `post/100` |
||||
(as barras (“/”) iniciais e finais serão ignoradas) combinando com o padrão `post/(\d+)`. |
||||
|
||||
Além de declarar regras de URL como pares de padrão-rota, você também pode declarar |
||||
como array. Cada array é utilizado para configurar um único objeto da regra de URL. |
||||
Isto se faz necessário quando você deseja configurar outras propriedades de uma |
||||
regra de URL. Por exemplo, |
||||
|
||||
```php |
||||
[ |
||||
// ...outras regras de URL... |
||||
|
||||
[ |
||||
'pattern' => 'posts', |
||||
'route' => 'post/index', |
||||
'suffix' => '.json', |
||||
], |
||||
] |
||||
``` |
||||
|
||||
Por padrão, se você não especificar a opção `class` na configuração de uma regra, |
||||
será utilizado a classe [[yii\web\UrlRule]]. |
||||
|
||||
|
||||
### Parâmetros Nomeados <span id="named-parameters"></span> |
||||
|
||||
Uma regra de URL pode ser associado a alguns parâmetros nomeados que são |
||||
especificados no padrão `<ParamName:RegExp>`, onde o `ParamName` especifica o |
||||
nome do parâmetro e o `RegExp` especifica uma expressão regular opcional usada |
||||
para corresponder ao valor do parâmetro. Se o `RegExp` são for especificado, |
||||
significará que o valor do parâmetro será uma string sem barras (“/”). |
||||
|
||||
> Observação: Você apenas pode especificar expressões regulares para os parâmetros. |
||||
As demais partes de um padrão serão considerados como um texto simples. |
||||
|
||||
Quando esta regra for utilizada para analisar uma URL, os parâmetros associados |
||||
serão preenchidos com os valores que foram correspondidos pela regra e estes |
||||
parâmetros serão disponibilizados logo a seguir no `$_GET` pelo componente da |
||||
aplicação `request`. |
||||
|
||||
Vamos utilizar alguns exemplos para demonstrar como os parâmetros nomeados |
||||
funcionam. Supondo que declaramos as três regras a seguir: |
||||
|
||||
```php |
||||
[ |
||||
'posts/<year:\d{4}>/<category>' => 'post/index', |
||||
'posts' => 'post/index', |
||||
'post/<id:\d+>' => 'post/view', |
||||
] |
||||
``` |
||||
|
||||
Quando as regras forem utilizadas para analisar as URLs: |
||||
|
||||
- `/index.php/posts` obterá a rota `post/index` usando a segunda regra; |
||||
- `/index.php/posts/2014/php` obterá a rota `post/index`, o parâmetro `year` |
||||
cujo o valor é 2014 e o parâmetro `category` cujo valor é `php` usando a primeira regra; |
||||
- `/index.php/post/100` obterá a rota `post/view` e o parâmetro `id` cujo valor |
||||
é 100 usando a terceira regra; |
||||
- `/index.php/posts/php` causará uma exceção [[yii\web\NotFoundHttpException]] |
||||
quando a propriedade [[yii\web\UrlManager::enableStrictParsing]] for `true`, |
||||
por não ter correspondido a nenhum dos padrões. Se a propriedade |
||||
[[yii\web\UrlManager::enableStrictParsing]] for `false` (o valor padrão), o |
||||
caminho `posts/php` será retornado como uma rota. |
||||
|
||||
E quando as regras fores utilizadas para criar as URLs: |
||||
|
||||
- `Url::to(['post/index'])` cria `/index.php/posts` usando a segunda regra; |
||||
- `Url::to(['post/index', 'year' => 2014, 'category' => 'php'])` cria `/index.php/posts/2014/php` usando a primeira regra; |
||||
- `Url::to(['post/view', 'id' => 100])` cria `/index.php/post/100` usando a terceira regra; |
||||
- `Url::to(['post/view', 'id' => 100, 'source' => 'ad'])` cria `/index.php/post/100?source=ad` usando a terceira regra. |
||||
Pela razão do parâmetro `source` não foi especificado na regra, ele será acrescentado como uma query string na criação da URL. |
||||
- `Url::to(['post/index', 'category' => 'php'])` cria `/index.php/post/index?category=php` usando nenhuma das regras. |
||||
Observe que, se nenhuma das regras forem aplicadas, a URL será criada simplesmente |
||||
como a rota sendo o caminho e todos os parâmetros como query string. |
||||
|
||||
|
||||
### Parametrizando Rotas <span id="parameterizing-routes"></span> |
||||
|
||||
Você pode incorporar nomes de parâmetros na rota de uma regra de URL. Isto permite |
||||
que uma regra de URL seja utilizada para combinar diversas rotas. Por exemplo, a |
||||
regra a seguir incorpora os parâmetros `controller` e `action` nas rotas. |
||||
|
||||
```php |
||||
[ |
||||
'<controller:(post|comment)>/<id:\d+>/<action:(create|update|delete)>' => '<controller>/<action>', |
||||
'<controller:(post|comment)>/<id:\d+>' => '<controller>/view', |
||||
'<controller:(post|comment)>s' => '<controller>/index', |
||||
] |
||||
``` |
||||
|
||||
Para analisar uma URL `/index.php/comment/100/create`, a primeira regra será |
||||
aplicada, na qual foi definida o parâmetro `controller` para ser `comment` e o |
||||
parâmetro `action` para ser `create`. Sendo assim, a rota `<controller>/<action>` |
||||
é resolvida como `comment/create`. |
||||
|
||||
De forma similar, para criar uma URL com a rota `comment/index`, a terceira regra |
||||
será aplicada, criando um URL `/index.php/comments`. |
||||
|
||||
> Informação: Pela parametrização de rotas, é possível reduzir significativamente |
||||
o número de regras de URL, que também pode melhorar o desempenho do |
||||
[[yii\web\UrlManager|gerenciador de URL]]. |
||||
|
||||
Por padrão, todos os parâmetros declarados nas regras são obrigatórios. Se uma |
||||
URL da requisição não contiver um dos parâmetros em particular, ou se a URL está |
||||
sendo criado sem um dos parâmetros em particular, a regra não será aplicada. Para |
||||
fazer com que algum parâmetro em particular seja opcional, você pode configurar |
||||
a propriedade [[yii\web\UrlRule::defaults|defaults]] da regra. Os parâmetros |
||||
listados nesta propriedade são opcionais e serão utilizados quando os mesmos não |
||||
forem fornecidos. |
||||
|
||||
A declaração da regra a seguir, ambos os parâmetros `page` e `tag` são opcionais |
||||
e utilizarão o valor 1 e a string vazia, respectivamente, quando não forem fornecidos. |
||||
|
||||
```php |
||||
[ |
||||
// ...outras regras... |
||||
[ |
||||
'pattern' => 'posts/<page:\d+>/<tag>', |
||||
'route' => 'post/index', |
||||
'defaults' => ['page' => 1, 'tag' => ''], |
||||
], |
||||
] |
||||
``` |
||||
|
||||
A regra anterior pode ser usado para analisar ou criar qualquer uma das seguintes URLs: |
||||
|
||||
* `/index.php/posts`: `page` é 1, `tag` é ''. |
||||
* `/index.php/posts/2`: `page` é 2, `tag` is ''. |
||||
* `/index.php/posts/2/news`: `page` é 2, `tag` é `'news'`. |
||||
* `/index.php/posts/news`: `page` é 1, `tag` é `'news'`. |
||||
|
||||
Sem o uso dos parâmetros opcionais, você deveria criar 4 regras para alcançar o |
||||
mesmo resultado. |
||||
|
||||
|
||||
### Regras com Domínios <span id="rules-with-server-names"></span> |
||||
|
||||
É possível incluir domínios nos padrões das regras de URL. Isto é útil quando sua |
||||
aplicação se comporta de forma diferente em diferentes domínios. Por exemplo, a |
||||
regra a seguir obtém a rota `admin/user/login` pela análise da URL |
||||
`http://admin.example.com/login` e a rota `site/login` pela análise da URL |
||||
`http://www.example.com/login`. |
||||
|
||||
```php |
||||
[ |
||||
'http://admin.example.com/login' => 'admin/user/login', |
||||
'http://www.example.com/login' => 'site/login', |
||||
] |
||||
``` |
||||
|
||||
Você também pode incorporar parâmetros nos domínios para extrair informações |
||||
dinamicamente a partir deles. Por exemplo, a regra a seguir obtém a rota |
||||
`post/index` e o parâmetro `language=en` pela análise da URL `http://en.example.com/posts` |
||||
|
||||
```php |
||||
[ |
||||
'http://<language:\w+>.example.com/posts' => 'post/index', |
||||
] |
||||
``` |
||||
|
||||
> Observação: Regras com domínios NÃO devem ser incluídos com subpastas do script |
||||
de entrada em seus padrões. Por exemplo, se a aplicação estiver sob |
||||
`http://www.example.com/sandbox/blog`, você deve usar o padrão |
||||
`http://www.example.com/posts` ao invés de `http://www.example.com/sandbox/blog/posts`. |
||||
Isto permite que sua aplicação seja implantado sob qualquer diretório sem a |
||||
necessidade de alterar o código da aplicação. |
||||
|
||||
|
||||
### Sufixos da URL <span id="url-suffixes"></span> |
||||
|
||||
Você pode querer adicionar sufixos nas URLs para diversos fins. Por exemplo, |
||||
você pode adicionar o `.html` nas URLs para que se pareçam com páginas estáticas. |
||||
Você também pode adicionar o `.json` nas URLs para indicar o tipo de conteúdo |
||||
esperado na resposta. Você pode alcançar este objetivo configurando a propriedade |
||||
[[yii\web\UrlManager::suffix]] na configuração da aplicação conforme o exemplo a seguir: |
||||
|
||||
```php |
||||
[ |
||||
'components' => [ |
||||
'urlManager' => [ |
||||
'enablePrettyUrl' => true, |
||||
'showScriptName' => false, |
||||
'enableStrictParsing' => true, |
||||
'suffix' => '.html', |
||||
'rules' => [ |
||||
// ... |
||||
], |
||||
], |
||||
], |
||||
] |
||||
``` |
||||
|
||||
A configuração anterior permitirá que o [[yii\web\UrlManager|gerenciador de URL]] |
||||
reconheçam as URLs solicitadas e que também criem URLs com o prefixo `.html`. |
||||
|
||||
> Dica: Você pode definir `/` como o sufixo para que todas as URLs terminem com barra. |
||||
|
||||
> Observação: Ao configurar um sufixo da URL e a URL da requisição não conter um, |
||||
será considerado como uma URL não válida. Isto é uma prática recomendada no |
||||
SEO (otimização para mecanismos de pesquisa, do *inglês search engine optimization*). |
||||
|
||||
Ás vezes você poder querer utilizar diferentes sufixos para diferentes URLs. |
||||
Isto pode ser alcançado pela configuração da propriedade |
||||
[[yii\web\UrlRule::suffix|suffix]] individualmente para cada regra de URL. |
||||
Quando uma regra de URL possuir esta propriedade definida, sobrescreverá o |
||||
sufixo que foi definido da camada do [[yii\web\UrlManager|gerenciador de URL]]. |
||||
Por exemplo, a configuração a seguir contém uma regra de URL personalizada que |
||||
usa o `.json` como sufixo ao invés do sufixo `.html` definido globalmente. |
||||
|
||||
```php |
||||
[ |
||||
'components' => [ |
||||
'urlManager' => [ |
||||
'enablePrettyUrl' => true, |
||||
'showScriptName' => false, |
||||
'enableStrictParsing' => true, |
||||
'suffix' => '.html', |
||||
'rules' => [ |
||||
// ... |
||||
[ |
||||
'pattern' => 'posts', |
||||
'route' => 'post/index', |
||||
'suffix' => '.json', |
||||
], |
||||
], |
||||
], |
||||
], |
||||
] |
||||
``` |
||||
|
||||
|
||||
### Métodos HTTP <span id="http-methods"></span> |
||||
|
||||
Ao implementar RESTful API, é necessário que sejam obtidas rotas diferentes pela |
||||
análise de uma mesma URL de acordo com o método HTTP utilizado. Isto pode ser |
||||
alcançado facilmente adicionando o prefixo do método HTTP suportado, separando |
||||
os nomes dos métodos por vírgulas. Por exemplo, a regra a seguir possui o mesmo |
||||
padrão `post/<id:\d+>` com suporte a diferentes métodos HTTP. A análise de uma |
||||
requisição `PUT post/100` obterá a rota `post/create`, enquanto a requisição |
||||
`GET post/100` obterá a rota `post/view`. |
||||
|
||||
```php |
||||
[ |
||||
'PUT,POST post/<id:\d+>' => 'post/create', |
||||
'DELETE post/<id:\d+>' => 'post/delete', |
||||
'post/<id:\d+>' => 'post/view', |
||||
] |
||||
``` |
||||
|
||||
> Observação: Se uma regra de URL contiver método(s) HTTP, esta regra só será |
||||
utilizada para análises de URLs. A regra será ignorada quando o |
||||
[[yii\web\UrlManager|gerenciador de URL]] for chamado para criar URLs. |
||||
|
||||
> Dica: Para simplificar o roteamento do RESTful APIs, o Yii fornece uma classe |
||||
especial [[yii\rest\UrlRule]] de regras que é muito diferente. Esta classe |
||||
suporta muitos recursos como a pluralização automática de IDs do controller |
||||
(controlador). Para mais detalhes, por favor, consulte a seção |
||||
[Routing](rest-routing.md) sobre o desenvolvimento de RESTful APIs. |
||||
|
||||
|
||||
### Regras Personalizadas <span id="customizing-rules"></span> |
||||
|
||||
Nos exemplo anteriores, as regras de URL são declaradas principalmente no formato |
||||
de pares de padrão-rota. Este é um formato de atalho bastante utilizado. Em |
||||
alguns cenários, você pode querer personalizar uma regra de URL configurando |
||||
outras propriedades, tais como o [[yii\web\UrlRule::suffix]]. Isto pode ser |
||||
feito utilizando um array de configuração para especificar uma regra. O exemplo |
||||
a seguir foi retirado da subseção [Sufixos da URL](#url-suffixes), |
||||
|
||||
```php |
||||
[ |
||||
// ...outras regras de URL... |
||||
|
||||
[ |
||||
'pattern' => 'posts', |
||||
'route' => 'post/index', |
||||
'suffix' => '.json', |
||||
], |
||||
] |
||||
``` |
||||
|
||||
> Informações: Por padrão, se você não especificar a opção `class` na configuração |
||||
de uma regra, será usado como padrão a classe [[yii\web\UrlRule]]. |
||||
|
||||
|
||||
### Adicionando Regras Dinamicamente <span id="adding-rules"></span> |
||||
|
||||
As regras de URL podem ser adicionadas dinamicamente ao [[yii\web\UrlManager|gerenciador de URL]]. |
||||
Esta técnica muitas vezes se faz necessária em [módulos](structure-modules.md) que |
||||
são redistribuídos e que desejam gerenciar as suas próprias regras de URL. Para |
||||
que estas regras sejam adicionadas dinamicamente e terem efeito durante o processo |
||||
de roteamento, você pode adiciona-los durante a [inicialização (bootstrapping)](runtime-bootstrapping.md). |
||||
Para os módulos, significa que deve implementar a interface [[yii\base\BootstrapInterface]] |
||||
e adicionar as regras no método [[yii\base\BootstrapInterface::bootstrap()|bootstrap()]] |
||||
conforme o exemplo a seguir: |
||||
|
||||
```php |
||||
public function bootstrap($app) |
||||
{ |
||||
$app->getUrlManager()->addRules([ |
||||
// declare as regras aqui |
||||
], false); |
||||
} |
||||
``` |
||||
|
||||
Observe que você também deve listar estes módulos no [[yii\web\Application::bootstrap]] |
||||
para que eles sejam usados no processo de [inicialização (bootstrapping)](runtime-bootstrapping.md) |
||||
|
||||
|
||||
### Criando Classes de Regras <span id="creating-rules"></span> |
||||
|
||||
Apesar do fato que a classe padrão [[yii\web\UrlRule]] é flexível o suficiente |
||||
para a maior parte dos projetos, há situações em que você terá que criar a sua |
||||
própria classe de regra. Por exemplo, em um site de venda de carros, você pode |
||||
querer dar suporte a um formato de URL como `/Manufacturer/Model`, que tanto o |
||||
`Manufacturer` quanto o `Model` devem coincidir com os dados armazenados em uma |
||||
tabela do banco de dados. A classe de regra padrão não vai funcionar nesta |
||||
situação pois vão se basear em padrões estaticamente declarados. |
||||
|
||||
Podemos criar uma classe de regra de URL para resolver este formato. |
||||
|
||||
```php |
||||
namespace app\components; |
||||
|
||||
use yii\web\UrlRuleInterface; |
||||
use yii\base\Object; |
||||
|
||||
class CarUrlRule extends Object implements UrlRuleInterface |
||||
{ |
||||
|
||||
public function createUrl($manager, $route, $params) |
||||
{ |
||||
if ($route === 'car/index') { |
||||
if (isset($params['manufacturer'], $params['model'])) { |
||||
return $params['manufacturer'] . '/' . $params['model']; |
||||
} elseif (isset($params['manufacturer'])) { |
||||
return $params['manufacturer']; |
||||
} |
||||
} |
||||
return false; // esta regra não se aplica |
||||
} |
||||
|
||||
public function parseRequest($manager, $request) |
||||
{ |
||||
$pathInfo = $request->getPathInfo(); |
||||
if (preg_match('%^(\w+)(/(\w+))?$%', $pathInfo, $matches)) { |
||||
// checa o $matches[1] e $matches[3] para verificar |
||||
// se coincidem com um *fabricante* e um *modelo* no banco de dados. |
||||
// Caso coincida, define o $params['manufacturer'] e/ou $params['model'] |
||||
// e retorna ['car/index', $params] |
||||
} |
||||
return false; // esta regra não se aplica |
||||
} |
||||
} |
||||
``` |
||||
|
||||
E utilize esta nova classe de regra na configuração [[yii\web\UrlManager::rules]]: |
||||
|
||||
```php |
||||
[ |
||||
// ...outras regras... |
||||
|
||||
[ |
||||
'class' => 'app\components\CarUrlRule', |
||||
// ...configurar outras propriedades... |
||||
], |
||||
] |
||||
``` |
||||
|
||||
|
||||
## Considerando Performance <span id="performance-consideration"></span> |
||||
|
||||
Ao desenvolver uma aplicação Web complexa, é importante otimizar as regras de URL |
||||
para que leve menos tempo na análise de requisições e criação de URLs. |
||||
|
||||
Utilizando rotas parametrizadas, você reduz o número de regras de URL, na qual |
||||
pode melhorar significativamente o desempenho. |
||||
|
||||
Na análise e criação de URLs, o [[yii\web\UrlManager|gerenciador de URL]] examina |
||||
as regras de URL na ordem em que foram declaradas. |
||||
Portanto, você pode considerar ajustar a ordem destas regras, fazendo com que as |
||||
regras mais específicas e/ou mais comuns sejam colocadas antes que os menos. |
||||
|
||||
Se algumas regras de URL compartilharem o mesmo prefixo em seus padrões ou rotas, |
||||
você pode considerar utilizar o [[yii\web\GroupUrlRule]] para que sejam examinados |
||||
de forma mais eficiente pelo [[yii\web\UrlManager|gerenciador de URL]] como um |
||||
grupo. Normalmente é o caso de aplicações compostos por módulos, onde cada módulo |
||||
possui o seu próprio conjunto de regras de URL utilizando o ID do módulo como |
||||
prefixo comum. |
@ -0,0 +1,636 @@
|
||||
Объекты доступа к данным (DAO) |
||||
============================== |
||||
|
||||
Построенные поверх [PDO](http://php.net/manual/ru/book.pdo.php), Yii DAO (объекты доступа к данным) обеспечивают |
||||
объектно-ориентированный API для доступа к реляционным базам данных. Это основа для других, более продвинутых, методов |
||||
доступа к базам данных, включая [построитель запросов](db-query-builder.md) и [active record](db-active-record.md). |
||||
|
||||
При использовании Yii DAO вы в основном будете использовать чистый SQL и массивы PHP. Как результат, это самый |
||||
эффективный способ доступа к базам данных. Тем не менее, так как синтаксис SQL может отличаться для разных баз данных, |
||||
используя Yii DAO вам нужно будет приложить дополнительные усилия, чтобы сделать приложение не зависящим от конкретной |
||||
базы данных. |
||||
|
||||
Yii DAO из коробки поддерживает следующие базы данных: |
||||
|
||||
- [MySQL](http://www.mysql.com/) |
||||
- [MariaDB](https://mariadb.com/) |
||||
- [SQLite](http://sqlite.org/) |
||||
- [PostgreSQL](http://www.postgresql.org/) |
||||
- [CUBRID](http://www.cubrid.org/): версии 9.3 или выше. |
||||
- [Oracle](http://www.oracle.com/us/products/database/overview/index.html) |
||||
- [MSSQL](https://www.microsoft.com/en-us/sqlserver/default.aspx): версии 2008 или выше. |
||||
|
||||
|
||||
## Создание подключения к базе данных <span id="creating-db-connections"></span> |
||||
|
||||
Для доступа к базе данных, вы сначала должны подключится к ней, создав экземпляр класса [[yii\db\Connection]]: |
||||
|
||||
```php |
||||
$db = new yii\db\Connection([ |
||||
'dsn' => 'mysql:host=localhost;dbname=example', |
||||
'username' => 'root', |
||||
'password' => '', |
||||
'charset' => 'utf8', |
||||
]); |
||||
``` |
||||
|
||||
Так как подключение к БД часто нужно в нескольких местах, распространённой практикой является его настройка как |
||||
[компонента приложения](structure-application-components.md): |
||||
|
||||
```php |
||||
return [ |
||||
// ... |
||||
'components' => [ |
||||
// ... |
||||
'db' => [ |
||||
'class' => 'yii\db\Connection', |
||||
'dsn' => 'mysql:host=localhost;dbname=example', |
||||
'username' => 'root', |
||||
'password' => '', |
||||
'charset' => 'utf8', |
||||
], |
||||
], |
||||
// ... |
||||
]; |
||||
``` |
||||
|
||||
Теперь вы можете получить доступ к подключению к БД с помощью выражения `Yii::$app->db`. |
||||
|
||||
> Подсказка: Вы можете настроить несколько компонентов подключения, если в вашем приложении используется несколько баз данных. |
||||
|
||||
При настройке подключения, вы должны обязательно указывать Имя Источника Данных (DSN) через параметр [[yii\db\Connection::dsn|dsn]]. |
||||
Формат DSN отличается для разных баз данных. По |
||||
The format of DSN varies for different databases. Дополнительное описание смотрите в [справочнике PHP](http://php.net/manual/ru/pdo.construct.php). |
||||
Ниже представлены несколько примеров: |
||||
|
||||
* MySQL, MariaDB: `mysql:host=localhost;dbname=mydatabase` |
||||
* SQLite: `sqlite:/path/to/database/file` |
||||
* PostgreSQL: `pgsql:host=localhost;port=5432;dbname=mydatabase` |
||||
* CUBRID: `cubrid:dbname=demodb;host=localhost;port=33000` |
||||
* MS SQL Server (via sqlsrv driver): `sqlsrv:Server=localhost;Database=mydatabase` |
||||
* MS SQL Server (via dblib driver): `dblib:host=localhost;dbname=mydatabase` |
||||
* MS SQL Server (via mssql driver): `mssql:host=localhost;dbname=mydatabase` |
||||
* Oracle: `oci:dbname=//localhost:1521/mydatabase` |
||||
|
||||
Заметьте, что если вы подключаетесь к базе данных через ODBC, вам необходимо указать свойство [[yii\db\Connection::driverName]], |
||||
чтобы Yii знал какой тип базы данных используется. Например: |
||||
|
||||
```php |
||||
'db' => [ |
||||
'class' => 'yii\db\Connection', |
||||
'driverName' => 'mysql', |
||||
'dsn' => 'odbc:Driver={MySQL};Server=localhost;Database=test', |
||||
'username' => 'root', |
||||
'password' => '', |
||||
], |
||||
``` |
||||
|
||||
Кроме свойства [[yii\db\Connection::dsn|dsn]], вам необходимо указать [[yii\db\Connection::username|username]] |
||||
и [[yii\db\Connection::password|password]]. Смотрите [[yii\db\Connection]] для того, чтоб посмотреть полный список свойств. |
||||
|
||||
> Информация: При создании экземпляра соединения к БД, фактическое соединение с базой данных будет установлено только |
||||
при выполнении первого SQL запроса или при явном вызове метода [[yii\db\Connection::open()|open()]]. |
||||
|
||||
> Подсказка: Иногда может потребоваться выполнить некоторые запросы сразу после соединения с базой данных, для инициализации |
||||
> переменных окружения. Вы можете зарегистрировать обработчик для события [[yii\db\Connection::EVENT_AFTER_OPEN|afterOpen]]. |
||||
> Вы можете зарегистрировать обработчик прямо в конфигурации приложения: |
||||
> |
||||
> ```php |
||||
> 'db' => [ |
||||
> // ... |
||||
> 'on afterOpen' => function($event) { |
||||
> $event->sender->createCommand("YOUR SQL HERE")->execute(); |
||||
> } |
||||
> ] |
||||
> ``` |
||||
|
||||
## Выполнение SQL запросов <span id="executing-sql-queries"></span> |
||||
|
||||
После создания экземпляра соединения, вы можете выполнить SQL запрос, выполнив следующие шаги: |
||||
|
||||
1. Создать [[yii\db\Command]] с текстом SQL; |
||||
2. Привязать параметры (не обязательно); |
||||
3. Вызвать один из методов выполнения SQL из [[yii\db\Command]]. |
||||
|
||||
Следующий пример показывает различные способы получения данных из базы дынных: |
||||
|
||||
```php |
||||
$db = new yii\db\Connection(...); |
||||
|
||||
// возвращает набор строк. каждая строка - это ассоциативный массив с именами столбцов и значений. |
||||
// если выборка ничего не вернёт, то будет возвращён пустой массив. |
||||
$posts = $db->createCommand('SELECT * FROM post') |
||||
->queryAll(); |
||||
|
||||
// вернёт одну строку (первую строку) |
||||
// ложь, если ничего не будет выбрано |
||||
$post = $db->createCommand('SELECT * FROM post WHERE id=1') |
||||
->queryOne(); |
||||
|
||||
// вернёт один столбец (первый столбец) |
||||
// пустой массив, при отсутствии результата |
||||
$titles = $db->createCommand('SELECT title FROM post') |
||||
->queryColumn(); |
||||
|
||||
// вернёт значение |
||||
// ложь, при отсутствии результата |
||||
$count = $db->createCommand('SELECT COUNT(*) FROM post') |
||||
->queryScalar(); |
||||
``` |
||||
|
||||
> Примечание: Чтобы сохранить точность, данные извлекаются как строки, даже если тип поля в базе данных является числовым. |
||||
|
||||
> Подсказка: Если вам необходимо выполнить SQL запрос сразу после установки соединения (например, для установки |
||||
> временной зоны или кодировки), вы можете сделать это в обработчике события [[yii\db\Connection::EVENT_AFTER_OPEN]]. |
||||
> Например: |
||||
```php |
||||
return [ |
||||
// ... |
||||
'components' => [ |
||||
// ... |
||||
'db' => [ |
||||
'class' => 'yii\db\Connection', |
||||
// ... |
||||
'on afterOpen' => function($event) { |
||||
// $event->sender ссылка на соединение с базой данных |
||||
$event->sender->createCommand("SET time_zone = 'UTC'")->execute(); |
||||
} |
||||
], |
||||
], |
||||
// ... |
||||
]; |
||||
``` |
||||
|
||||
|
||||
### Привязка параметров <span id="binding-parameters"></span> |
||||
|
||||
При создании команды из SQL запроса с параметрами, вы почти всегда должны использовать привязку параметров для |
||||
предотвращения атак через SQL инъекции. Например: |
||||
|
||||
```php |
||||
$post = $db->createCommand('SELECT * FROM post WHERE id=:id AND status=:status') |
||||
->bindValue(':id', $_GET['id']) |
||||
->bindValue(':status', 1) |
||||
->queryOne(); |
||||
``` |
||||
|
||||
В SQL запрос, вы можете встраивать один или несколько маркеров (например `:id` в примере выше). Маркеры должны быть |
||||
строкой начинающейся с двоеточия. Далее вам нужно вызвать один из следующих методов для привязки значений к параметрам: |
||||
|
||||
* [[yii\db\Command::bindValue()|bindValue()]]: привязка одного параметра по значению |
||||
* [[yii\db\Command::bindValues()|bindValues()]]: привязка нескольких параметров в одном вызове |
||||
* [[yii\db\Command::bindParam()|bindParam()]]: похоже на [[yii\db\Command::bindValue()|bindValue()]] но привязка |
||||
происходит по ссылке. |
||||
|
||||
Следующий пример показывает альтернативный путь привязки параметров: |
||||
|
||||
```php |
||||
$params = [':id' => $_GET['id'], ':status' => 1]; |
||||
|
||||
$post = $db->createCommand('SELECT * FROM post WHERE id=:id AND status=:status') |
||||
->bindValues($params) |
||||
->queryOne(); |
||||
|
||||
$post = $db->createCommand('SELECT * FROM post WHERE id=:id AND status=:status', $params) |
||||
->queryOne(); |
||||
``` |
||||
|
||||
Привязка переменных реализована через [подготавливаемые запросы](http://php.net/manual/ru/mysqli.quickstart.prepared-statements.php). |
||||
Помимо предотвращения атак путём SQL инъекций, это увеличивает производительность, так как запрос подготавливается |
||||
один раз, а потом выполняется много раз с разными параметрами. Например: |
||||
|
||||
```php |
||||
$command = $db->createCommand('SELECT * FROM post WHERE id=:id'); |
||||
|
||||
$post1 = $command->bindValue(':id', 1)->queryOne(); |
||||
$post2 = $command->bindValue(':id', 2)->queryOne(); |
||||
``` |
||||
|
||||
Так как [[yii\db\Command::bindParam()|bindParam()]] поддерживает привязку параметров по ссылке, следующий код может |
||||
быть написан следующим образом: |
||||
|
||||
```php |
||||
$command = $db->createCommand('SELECT * FROM post WHERE id=:id') |
||||
->bindParam(':id', $id); |
||||
|
||||
$id = 1; |
||||
$post1 = $command->queryOne(); |
||||
|
||||
$id = 2; |
||||
$post2 = $command->queryOne(); |
||||
``` |
||||
|
||||
Обратите внимание что вы связываете маркер `$id` с переменной перед выполнением запроса, и затем меняете это значение |
||||
перед каждым последующим выполнением (часто это делается в цикле). Выполнении запросов таким образом может быть значительно |
||||
более эффективным, чем выполнение запроса для каждого значения параметра. |
||||
|
||||
### Выполнение Не-SELECT запросов <span id="non-select-queries"></span> |
||||
|
||||
В методах `queryXyz()`, описанных в предыдущих разделах, вызываются SELECT запросы для извлечения данных из базы. |
||||
Для запросов не возвращающих данные, вы должны использовать метод [[yii\db\Command::execute()]]. Например: |
||||
|
||||
```php |
||||
$db->createCommand('UPDATE post SET status=1 WHERE id=1') |
||||
->execute(); |
||||
``` |
||||
|
||||
Метод [[yii\db\Command::execute()]] возвращает количество строк обработанных SQL запросом. |
||||
|
||||
Для запросов INSERT, UPDATE и DELETE, вместо написания чистого SQL, вы можете вызвать методы [[yii\db\Command::insert()|insert()]], |
||||
[[yii\db\Command::update()|update()]], [[yii\db\Command::delete()|delete()]], соответственно, для создания указанных |
||||
SQL конструкций. Например: |
||||
|
||||
```php |
||||
// INSERT (table name, column values) |
||||
$db->createCommand()->insert('user', [ |
||||
'name' => 'Sam', |
||||
'age' => 30, |
||||
])->execute(); |
||||
|
||||
// UPDATE (table name, column values, condition) |
||||
$db->createCommand()->update('user', ['status' => 1], 'age > 30')->execute(); |
||||
|
||||
// DELETE (table name, condition) |
||||
$db->createCommand()->delete('user', 'status = 0')->execute(); |
||||
``` |
||||
|
||||
Вы можете также вызвать [[yii\db\Command::batchInsert()|batchInsert()]] для вставки множества строк за один вызов. |
||||
Это более эффективно чем вставлять записи по одной за раз: |
||||
|
||||
```php |
||||
// table name, column names, column values |
||||
$db->createCommand()->batchInsert('user', ['name', 'age'], [ |
||||
['Tom', 30], |
||||
['Jane', 20], |
||||
['Linda', 25], |
||||
])->execute(); |
||||
``` |
||||
|
||||
|
||||
## Экранирование имён таблиц и столбцов <span id="quoting-table-and-column-names"></span> |
||||
|
||||
При написании независимого от базы данных кода, правильно экранировать имена таблиц и столбцов довольно трудно, так как |
||||
в разных базах данных правила экранирования разные. Чтоб преодолеть данную проблему вы можете использовать следующий |
||||
синтаксис экранирования используемый в Yii: |
||||
|
||||
* `[[column name]]`: заключайте имя столбца в двойные квадратные скобки; |
||||
* `{{table name}}`: заключайте имя таблицы в двойные фигурные скобки. |
||||
|
||||
Yii DAO будет автоматический преобразовывать подобные конструкции в SQL в правильно экранированные имена таблиц и столбцов. |
||||
Например, |
||||
|
||||
```php |
||||
// executes this SQL for MySQL: SELECT COUNT(`id`) FROM `employee` |
||||
$count = $db->createCommand("SELECT COUNT([[id]]) FROM {{employee}}") |
||||
->queryScalar(); |
||||
``` |
||||
|
||||
|
||||
### Использование префиксов таблиц <span id="using-table-prefix"></span> |
||||
|
||||
Если большинство ваших таблиц использует общий префикс в имени, вы можете использовать свойство Yii DAO для указания префикса. |
||||
|
||||
Сначала, укажите префикс таблиц через свойство [[yii\db\Connection::tablePrefix]]: |
||||
|
||||
```php |
||||
return [ |
||||
// ... |
||||
'components' => [ |
||||
// ... |
||||
'db' => [ |
||||
// ... |
||||
'tablePrefix' => 'tbl_', |
||||
], |
||||
], |
||||
]; |
||||
``` |
||||
|
||||
Затем в коде, когда вам нужно ссылаться на таблицу, имя которой содержит такой префикс, используйте синтаксис `{{%table name}}`. |
||||
Символ процента будет автоматический заменён на префикс таблицы, который вы указали во время конфигурации соединения с |
||||
базой данных. Например: |
||||
|
||||
```php |
||||
// для MySQL будет выполнен следующий SQL: SELECT COUNT(`id`) FROM `tbl_employee` |
||||
$count = $db->createCommand("SELECT COUNT([[id]]) FROM {{%employee}}") |
||||
->queryScalar(); |
||||
``` |
||||
|
||||
|
||||
## Исполнение транзакций <span id="performing-transactions"></span> |
||||
|
||||
Когда вы выполняете несколько зависимых запросов последовательно, вам может потребоваться обернуть их в транзакцию |
||||
для обеспечения целостности вашей базы данных. Если в любом из запросов произойдёт ошибка, база данных откатится на |
||||
состояние, которое было до выполнения запросов. |
||||
|
||||
Следующий код показывает типичное использование транзакций: |
||||
|
||||
```php |
||||
$db->transaction(function($db) { |
||||
$db->createCommand($sql1)->execute(); |
||||
$db->createCommand($sql2)->execute(); |
||||
// ... executing other SQL statements ... |
||||
}); |
||||
``` |
||||
|
||||
Код выше эквивалентен следующему: |
||||
|
||||
```php |
||||
$transaction = $db->beginTransaction(); |
||||
|
||||
try { |
||||
$db->createCommand($sql1)->execute(); |
||||
$db->createCommand($sql2)->execute(); |
||||
// ... executing other SQL statements ... |
||||
|
||||
$transaction->commit(); |
||||
|
||||
} catch(\Exception $e) { |
||||
|
||||
$transaction->rollBack(); |
||||
|
||||
throw $e; |
||||
} |
||||
``` |
||||
|
||||
При вызове метода [[yii\db\Connection::beginTransaction()|beginTransaction()]], будет запущена новая транзакция. |
||||
Транзакция представлена объектом [[yii\db\Transaction]] сохранённым в переменной `$transaction`. Потом, запросы будут |
||||
выполняться в блоке `try...catch...`. Если запросы будут выполнены удачно, будет выполнен метод [[yii\db\Transaction::commit()|commit()]]. |
||||
Иначе, будет вызвано исключение, и будет вызван метод [[yii\db\Transaction::rollBack()|rollBack()]] для отката |
||||
изменений сделанных до неудачно выполненного запроса внутри транзакции. |
||||
|
||||
### Указание уровня изоляции <span id="specifying-isolation-levels"></span> |
||||
|
||||
Yii поддерживает настройку [уровня изоляции] для ваших транзакций. По умолчанию, при старте транзакции, будет использован |
||||
уровень изоляции настроенный в вашей базе данных. Вы можете переопределить уровень изоляции по умолчанию, как |
||||
указано ниже: |
||||
|
||||
```php |
||||
$isolationLevel = \yii\db\Transaction::REPEATABLE_READ; |
||||
|
||||
$db->transaction(function ($db) { |
||||
.... |
||||
}, $isolationLevel); |
||||
|
||||
// or alternatively |
||||
|
||||
$transaction = $db->beginTransaction($isolationLevel); |
||||
``` |
||||
|
||||
Yii предоставляет четыре константы для наиболее распространённых уровней изоляции: |
||||
|
||||
- [[\yii\db\Transaction::READ_UNCOMMITTED]] - низший уровень, «Грязное» чтение, не повторяющееся чтение и фантомное чтение. |
||||
- [[\yii\db\Transaction::READ_COMMITTED]] - предотвращает «Грязное» чтение. |
||||
- [[\yii\db\Transaction::REPEATABLE_READ]] - предотвращает «Грязное» чтение и не повторяющееся чтение. |
||||
- [[\yii\db\Transaction::SERIALIZABLE]] - высший уровень, предотвращает все вышеуказанные проблемы. |
||||
|
||||
Помимо использования приведённых выше констант для задания уровня изоляции, вы можете также использовать строки с |
||||
поддерживаемые вашим СУБД. Например, в PostgreSQL, вы можете использовать `SERIALIZABLE READ ONLY DEFERRABLE`. |
||||
|
||||
Заметьте что некоторые СУБД допускают настраивать уровень изоляции только для всего соединения. Следующие транзакции |
||||
будут получать тот же уровень изоляции, даже если вы его не укажете. При использовании этой функции может потребоваться |
||||
установить уровень изоляции для всех транзакции, чтоб избежать явно конфликтующих настроек. |
||||
На момент написания этой статьи страдали от этого только MSSQL и SQLite. |
||||
|
||||
> Примечание: SQLite поддерживает только два уровня изоляции, таким образом вы можете использовать только |
||||
`READ UNCOMMITTED` и `SERIALIZABLE`. Использование других уровней изоляции приведёт к генерации исключения. |
||||
|
||||
> Примечание: PostgreSQL не допускает установки уровня изоляции до старта транзакции, так что вы не сможете установить |
||||
уровень изоляции прямо при старте транзакции. Вы можете использовать [[yii\db\Transaction::setIsolationLevel()]] в |
||||
таком случае после старта транзакции. |
||||
|
||||
[Уровни изоляции]: https://ru.wikipedia.org/wiki/%D0%A3%D1%80%D0%BE%D0%B2%D0%B5%D0%BD%D1%8C_%D0%B8%D0%B7%D0%BE%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D0%BE%D1%81%D1%82%D0%B8_%D1%82%D1%80%D0%B0%D0%BD%D0%B7%D0%B0%D0%BA%D1%86%D0%B8%D0%B9 |
||||
|
||||
|
||||
### Вложенные транзакции <span id="nesting-transactions"></span> |
||||
|
||||
Если ваша СУБД поддерживает Savepoint, вы можете вкладывать транзакции как показано ниже: |
||||
|
||||
```php |
||||
$db->transaction(function ($db) { |
||||
// outer transaction |
||||
|
||||
$db->transaction(function ($db) { |
||||
// inner transaction |
||||
}); |
||||
}); |
||||
``` |
||||
|
||||
Или так, |
||||
|
||||
```php |
||||
$outerTransaction = $db->beginTransaction(); |
||||
try { |
||||
$db->createCommand($sql1)->execute(); |
||||
|
||||
$innerTransaction = $db->beginTransaction(); |
||||
try { |
||||
$db->createCommand($sql2)->execute(); |
||||
$innerTransaction->commit(); |
||||
} catch (Exception $e) { |
||||
$innerTransaction->rollBack(); |
||||
} |
||||
|
||||
$outerTransaction->commit(); |
||||
} catch (Exception $e) { |
||||
$outerTransaction->rollBack(); |
||||
} |
||||
``` |
||||
|
||||
|
||||
## Репликация и разделение запросов на чтение и запись <span id="read-write-splitting"></span> |
||||
|
||||
Многие СУБД поддерживают [репликацию баз данных](http://en.wikipedia.org/wiki/Replication_(computing)#Database_replication) |
||||
для лучшей доступности базы данных и уменьшения времени ответа сервера. С репликацией базы данных, данные копируются |
||||
из *master servers* на *slave servers*. Все вставки и обновления должны происходить на основном сервере, хотя чтение |
||||
может производится и с подчинённых серверов. |
||||
|
||||
Чтоб воспользоваться преимуществами репликации и достичь разделения чтения и записи, вам необходимо настроить компонент |
||||
[[yii\db\Connection]] как указано ниже: |
||||
|
||||
```php |
||||
[ |
||||
'class' => 'yii\db\Connection', |
||||
|
||||
// настройки для мастера |
||||
'dsn' => 'dsn for master server', |
||||
'username' => 'master', |
||||
'password' => '', |
||||
|
||||
// общие настройки для подчинённых |
||||
'slaveConfig' => [ |
||||
'username' => 'slave', |
||||
'password' => '', |
||||
'attributes' => [ |
||||
// используем небольшой таймаут для соединения |
||||
PDO::ATTR_TIMEOUT => 10, |
||||
], |
||||
], |
||||
|
||||
// список настроек для подчинённых серверов |
||||
'slaves' => [ |
||||
['dsn' => 'dsn for slave server 1'], |
||||
['dsn' => 'dsn for slave server 2'], |
||||
['dsn' => 'dsn for slave server 3'], |
||||
['dsn' => 'dsn for slave server 4'], |
||||
], |
||||
] |
||||
``` |
||||
|
||||
Вышеуказанная конфигурация определяет систему с одним мастером и несколькими подчинёнными. Один из подчинённых |
||||
будет подключен и использован для чтения, в то время как мастер будет использоваться для запросов записи. |
||||
Такое разделение чтения и записи будет осуществлено автоматический с указанной конфигурацией. Например: |
||||
|
||||
```php |
||||
// создание экземпляра соединения, использующего вышеуказанную конфигурацию |
||||
$db = Yii::createObject($config); |
||||
|
||||
// запрос к одному из подчинённых |
||||
$rows = $db->createCommand('SELECT * FROM user LIMIT 10')->queryAll(); |
||||
|
||||
// запрос к мастеру |
||||
$db->createCommand("UPDATE user SET username='demo' WHERE id=1")->execute(); |
||||
``` |
||||
|
||||
> Информация: Запросы выполненные через [[yii\db\Command::execute()]] определяются как запросы на запись, а все |
||||
остальные запросы через один из "query" методов [[yii\db\Command]] воспринимаются как запросы на чтение. |
||||
Вы можете получить текущий статус соединения к подчинённому серверу через `$db->slave`. |
||||
|
||||
Компонент `Connection` поддерживает балансировку нагрузки и переключение при сбое для подчинённых серверов. |
||||
При выполнении первого запроса на чтение, компонент `Connection` будет случайным образом выбирать подчинённый сервер |
||||
и попытается подключиться к нему. Если сервер окажется "мёртвым", он попробует подключиться к другому. Если ни один |
||||
из подчинённых серверов не будет доступен, он подключится к мастеру. Если настроить |
||||
[[yii\db\Connection::serverStatusCache|кеш статуса серверов]], то недоступность серверов может быть запомнена, чтоб не |
||||
использоваться в течении [[yii\db\Connection::serverRetryInterval|заданного промежутка времени]]. |
||||
|
||||
> Информация: В конфигурации выше, таймаут соединения к подчинённому серверу настроен на 10 секунд. |
||||
Это означает, что если сервер не ответит за 10 секунд, он будет считаться "мёртвым". Вы можете отрегулировать |
||||
этот параметр исходя из настроек вашей среды. |
||||
|
||||
Вы также можете настроить несколько основных и несколько подчинённых серверов. Например: |
||||
|
||||
```php |
||||
[ |
||||
'class' => 'yii\db\Connection', |
||||
|
||||
// общая конфигурация для основных серверов |
||||
'masterConfig' => [ |
||||
'username' => 'master', |
||||
'password' => '', |
||||
'attributes' => [ |
||||
// используем небольшой таймаут для соединения |
||||
PDO::ATTR_TIMEOUT => 10, |
||||
], |
||||
], |
||||
|
||||
// список настроек для основных серверов |
||||
'masters' => [ |
||||
['dsn' => 'dsn for master server 1'], |
||||
['dsn' => 'dsn for master server 2'], |
||||
], |
||||
|
||||
// общие настройки для подчинённых |
||||
'slaveConfig' => [ |
||||
'username' => 'slave', |
||||
'password' => '', |
||||
'attributes' => [ |
||||
// используем небольшой таймаут для соединения |
||||
PDO::ATTR_TIMEOUT => 10, |
||||
], |
||||
], |
||||
|
||||
// список настроек для подчинённых серверов |
||||
'slaves' => [ |
||||
['dsn' => 'dsn for slave server 1'], |
||||
['dsn' => 'dsn for slave server 2'], |
||||
['dsn' => 'dsn for slave server 3'], |
||||
['dsn' => 'dsn for slave server 4'], |
||||
], |
||||
] |
||||
``` |
||||
|
||||
Конфигурация выше, определяет два основных и четыре подчинённых серверов. Компонент `Connection` поддерживает |
||||
балансировку нагрузки и переключение при сбое между основными серверами, также как и между подчинёнными. Различие |
||||
заключается в том, что когда ни к одному из основных серверов не удастся подключиться будет выброшено исключение. |
||||
|
||||
> Примечание: Когда вы используете свойство [[yii\db\Connection::masters|masters]] для настройки одного или нескольких |
||||
основных серверов, все остальные свойства для настройки соединения с базой данных (такие как `dsn`, `username`, `password`) |
||||
будут проигнорированы компонентом `Connection`. |
||||
|
||||
По умолчанию, транзакции используют соединение с основным сервером. И в рамках транзакции, все операции с БД будут |
||||
использовать соединение с основным сервером. Например, |
||||
|
||||
```php |
||||
// Транзакция запускается на основном сервере |
||||
$transaction = $db->beginTransaction(); |
||||
|
||||
try { |
||||
// оба запроса выполняются на основном сервере |
||||
$rows = $db->createCommand('SELECT * FROM user LIMIT 10')->queryAll(); |
||||
$db->createCommand("UPDATE user SET username='demo' WHERE id=1")->execute(); |
||||
|
||||
$transaction->commit(); |
||||
} catch(\Exception $e) { |
||||
$transaction->rollBack(); |
||||
throw $e; |
||||
} |
||||
``` |
||||
|
||||
Если вы хотите запустить транзакцию на подчинённом сервере, вы должны указать это явно, как показано ниже: |
||||
|
||||
```php |
||||
$transaction = $db->slave->beginTransaction(); |
||||
``` |
||||
|
||||
Иногда может потребоваться выполнить запрос на чтение через подключение к основному серверу. Это может быть достигнуто |
||||
с использованием метода `useMaster()`: |
||||
|
||||
```php |
||||
$rows = $db->useMaster(function ($db) { |
||||
return $db->createCommand('SELECT * FROM user LIMIT 10')->queryAll(); |
||||
}); |
||||
``` |
||||
|
||||
Вы также можете явно установить `$db->enableSlaves` в ложь, чтоб направлять все запросы к соединению с мастером. |
||||
|
||||
|
||||
## Работа со схемой базы данных <span id="database-schema"></span> |
||||
|
||||
Yii DAO предоставляет целый набор методов для управления схемой базы данных, таких как создание новых таблиц, удаление |
||||
столбцов из таблицы, и т.д.. Эти методы описаны ниже: |
||||
|
||||
* [[yii\db\Command::createTable()|createTable()]]: создание таблицы |
||||
* [[yii\db\Command::renameTable()|renameTable()]]: переименование таблицы |
||||
* [[yii\db\Command::dropTable()|dropTable()]]: удаление таблицы |
||||
* [[yii\db\Command::truncateTable()|truncateTable()]]: удаление всех записей в таблице |
||||
* [[yii\db\Command::addColumn()|addColumn()]]: добавление столбца |
||||
* [[yii\db\Command::renameColumn()|renameColumn()]]: переименование столбца |
||||
* [[yii\db\Command::dropColumn()|dropColumn()]]: удаление столбца |
||||
* [[yii\db\Command::alterColumn()|alterColumn()]]: преобразование столбца |
||||
* [[yii\db\Command::addPrimaryKey()|addPrimaryKey()]]: добавление первичного ключа |
||||
* [[yii\db\Command::dropPrimaryKey()|dropPrimaryKey()]]: удаление первичного ключа |
||||
* [[yii\db\Command::addForeignKey()|addForeignKey()]]: добавление внешнего ключа |
||||
* [[yii\db\Command::dropForeignKey()|dropForeignKey()]]: удаление внешнего ключа |
||||
* [[yii\db\Command::createIndex()|createIndex()]]: создания индекса |
||||
* [[yii\db\Command::dropIndex()|dropIndex()]]: удаление индекса |
||||
|
||||
Эти методы могут быть использованы, как указано ниже: |
||||
|
||||
```php |
||||
// CREATE TABLE |
||||
$db->createCommand()->createTable('post', [ |
||||
'id' => 'pk', |
||||
'title' => 'string', |
||||
'text' => 'text', |
||||
]); |
||||
``` |
||||
|
||||
Вы также сможете получить описание схемы таблицы через вызов метода [[yii\db\Connection::getTableSchema()|getTableSchema()]]. |
||||
Например: |
||||
|
||||
```php |
||||
$table = $db->getTableSchema('post'); |
||||
``` |
||||
|
||||
Метод вернёт объект [[yii\db\TableSchema]], который содержит информацию о столбцах таблицы, первичных ключах, внешних |
||||
ключах, и т.д.. Вся эта информация используется главным образом для [построителя запросов](db-query-builder.md) и |
||||
[active record](db-active-record.md), чтоб помочь вам писать независимый от базы данных код. |
@ -0,0 +1,644 @@
|
||||
Построитель запросов |
||||
==================== |
||||
|
||||
Построенный поверх [DAO](db-dao.md), построитель запросов позволяет конструировать SQL выражения в программируемом и |
||||
независимом от СУБД виде. В сравнении с написанием чистого SQL, использование построителя помогает вам писать |
||||
более читаемый связанный с SQL код и генерировать более безопасные SQL выражения. |
||||
|
||||
Использование построителя запросов, как правило, включает два этапа: |
||||
|
||||
1. Создание объекта [[yii\db\Query]] представляющего различные части (такие как `SELECT`, `FROM`) SQL выражения SELECT. |
||||
2. Выполнить запрос методом [[yii\db\Query]] (таким как `all()`) для извлечения данных из базы данных. |
||||
|
||||
Следующий код показывает обычное использование построителя запросов: |
||||
|
||||
```php |
||||
$rows = (new \yii\db\Query()) |
||||
->select(['id', 'email']) |
||||
->from('user') |
||||
->where(['last_name' => 'Smith']) |
||||
->limit(10) |
||||
->all(); |
||||
``` |
||||
|
||||
Приведённый выше код создаёт и выполняет следующее SQL выражение, где параметр `:last_name` привязывается к строке `'Smith'`. |
||||
|
||||
```sql |
||||
SELECT `id`, `email` |
||||
FROM `user` |
||||
WHERE `last_name` = :last_name |
||||
LIMIT 10 |
||||
``` |
||||
|
||||
> Информация: В основном вы будете работать с [[yii\db\Query]] вместо [[yii\db\QueryBuilder]]. Последний вызывается |
||||
неявно при вызове одного из методов запроса. [[yii\db\QueryBuilder]] это класс отвечающий за генерацию зависимого |
||||
от СУБД SQL выражения (такие как экранирование имён таблиц/столбцов) из независимых от СУБД объектов [[yii\db\Query]]. |
||||
|
||||
|
||||
## Построение запросов <span id="building-queries"></span> |
||||
|
||||
Создав объект [[yii\db\Query]], вы можете вызвать различные методы для создания различных частей SQL выражения. |
||||
Имена методов напоминают ключевые слова SQL, используемые в соответствующих частях SQL запроса. Например, |
||||
чтобы указать `FROM` часть запроса, вам нужно вызвать метод `from()`. Все методы построителя запросов возвращают |
||||
свой объект, который позволяет объединять несколько вызовов в цепочку. |
||||
|
||||
Далее будет описание каждого метода построителя запросов. |
||||
|
||||
### [[yii\db\Query::select()|select()]] <span id="select"></span> |
||||
|
||||
Метод [[yii\db\Query::select()|select()]] определяет фрагмент `SELECT` SQL запроса. Вы можете указать столбцы, которые |
||||
должны быть выбраны, они должны быть указаны в виде массива или строки. Имена столбцов автоматически экранируются |
||||
при создании SQL-запроса при его генерации из объекта [[yii\db\Query]]. |
||||
|
||||
```php |
||||
$query->select(['id', 'email']); |
||||
|
||||
// эквивалентно: |
||||
|
||||
$query->select('id, email'); |
||||
``` |
||||
|
||||
Имена столбцов могут быть выбраны вместе с префиксами таблиц и/или алиасами столбцов, также как при записи обычного SQL. |
||||
Например, |
||||
|
||||
```php |
||||
$query->select(['user.id AS user_id', 'email']); |
||||
|
||||
// эквивалентно: |
||||
|
||||
$query->select('user.id AS user_id, email'); |
||||
``` |
||||
|
||||
Если вы используете формат массива для указания столбцов, вы можете также указать ключи массива для указания алиасов столбцов. |
||||
Например, приведённый выше код может быть переписан: |
||||
|
||||
```php |
||||
$query->select(['user_id' => 'user.id', 'email']); |
||||
``` |
||||
|
||||
Если вы не вызываете метод [[yii\db\Query::select()|select()]] при создании запроса, будет использована `*`, что означает |
||||
выбрать *все* столбцы. |
||||
|
||||
Кроме имён столбцов, вы можете также использовать SQL выражения. Вы должны использовать формат массива для использования |
||||
выражений, которые содержат запятые для предотвращения некорректного автоматического экранирования. Например: |
||||
|
||||
```php |
||||
$query->select(["CONCAT(first_name, ' ', last_name) AS full_name", 'email']); |
||||
``` |
||||
|
||||
Начиная с версии 2.0.1, вы также можете использовать подзапросы. Вы должны указывать каждый подзапрос в выражении как |
||||
объект [[yii\db\Query]]. Например: |
||||
|
||||
```php |
||||
$subQuery = (new Query())->select('COUNT(*)')->from('user'); |
||||
|
||||
// SELECT `id`, (SELECT COUNT(*) FROM `user`) AS `count` FROM `post` |
||||
$query = (new Query())->select(['id', 'count' => $subQuery])->from('post'); |
||||
``` |
||||
|
||||
Чтоб выбрать конкретные строки, вы можете вызвать метод [[yii\db\Query::distinct()|distinct()]]: |
||||
|
||||
```php |
||||
// SELECT DISTINCT `user_id` ... |
||||
$query->select('user_id')->distinct(); |
||||
``` |
||||
|
||||
Вы можете вызвать [[yii\db\Query::addSelect()|addSelect()]] для добавления полей. Например: |
||||
|
||||
```php |
||||
$query->select(['id', 'username']) |
||||
->addSelect(['email']); |
||||
``` |
||||
|
||||
|
||||
### [[yii\db\Query::from()|from()]] <span id="from"></span> |
||||
|
||||
Метод [[yii\db\Query::from()|from()]] указывает фрагмент `FROM` SQL запроса. Например: |
||||
|
||||
```php |
||||
// SELECT * FROM `user` |
||||
$query->from('user'); |
||||
``` |
||||
|
||||
Вы можете указать имена таблиц в виде строки или массива. Имена таблиц могут содержать префикс схемы и/или алиасы |
||||
таблиц, как при написании обычного SQL. Например: |
||||
|
||||
```php |
||||
$query->from(['public.user u', 'public.post p']); |
||||
|
||||
// эквивалентно: |
||||
|
||||
$query->from('public.user u, public.post p'); |
||||
``` |
||||
|
||||
Если вы используете формат массива, вы можете использовать ключи массива для указания алиасов: |
||||
|
||||
```php |
||||
$query->from(['u' => 'public.user', 'p' => 'public.post']); |
||||
``` |
||||
|
||||
Кроме имён таблиц, вы можете, также как и в select, указывать подзапросы в виде объекта [[yii\db\Query]]. |
||||
|
||||
```php |
||||
$subQuery = (new Query())->select('id')->from('user')->where('status=1'); |
||||
|
||||
// SELECT * FROM (SELECT `id` FROM `user` WHERE status=1) u |
||||
$query->from(['u' => $subQuery]); |
||||
``` |
||||
|
||||
|
||||
### [[yii\db\Query::where()|where()]] <span id="where"></span> |
||||
|
||||
Метод [[yii\db\Query::where()|where()]] определяет фрагмент `WHERE` SQL выражения. Вы можете использовать один из |
||||
трёх форматов: |
||||
|
||||
- строковый формат, например: `'status=1'` |
||||
- формат массива, например: `['status' => 1, 'type' => 2]` |
||||
- формат операторов, например: `['like', 'name', 'test']` |
||||
|
||||
|
||||
#### Строковый формат <span id="string-format"></span> |
||||
|
||||
Строковый формат - это лучший выбор для простых условий. Он работает так, будто вы просто пишете SQL запрос. Например: |
||||
|
||||
```php |
||||
$query->where('status=1'); |
||||
|
||||
// или используя привязку параметров |
||||
$query->where('status=:status', [':status' => $status]); |
||||
``` |
||||
|
||||
Не встраивайте переменные непосредственно в условие, особенно если значение переменной получено от пользователя, |
||||
потому что это делает ваше приложение подверженным атакам через SQL инъекции. |
||||
|
||||
```php |
||||
// Опасность! Не делайте так если вы не уверены, что $status это действительно число. |
||||
$query->where("status=$status"); |
||||
``` |
||||
|
||||
При использовании привязки параметров, вы можете вызывать [[yii\db\Query::params()|params()]] или |
||||
[[yii\db\Query::addParams()|addParams()]] для раздельного указания параметров. |
||||
|
||||
```php |
||||
$query->where('status=:status') |
||||
->addParams([':status' => $status]); |
||||
``` |
||||
|
||||
|
||||
#### Формат массива <span id="hash-format"></span> |
||||
|
||||
Формат массива лучше всего использовать для указания нескольких объединяемых через `AND` условий, каждое из которых |
||||
является простым равенством. Он описывается в виде массива, ключами которого являются имена столбцов, а значения |
||||
соответствуют значениям столбцов. |
||||
|
||||
```php |
||||
// ...WHERE (`status` = 10) AND (`type` IS NULL) AND (`id` IN (4, 8, 15)) |
||||
$query->where([ |
||||
'status' => 10, |
||||
'type' => null, |
||||
'id' => [4, 8, 15], |
||||
]); |
||||
``` |
||||
|
||||
Как вы можете видеть, построитель запросов достаточно умен, чтобы правильно обрабатывать значения NULL или массивов. |
||||
|
||||
Вы также можете использовать подзапросы: |
||||
|
||||
```php |
||||
$userQuery = (new Query())->select('id')->from('user'); |
||||
|
||||
// ...WHERE `id` IN (SELECT `id` FROM `user`) |
||||
$query->where(['id' => $userQuery]); |
||||
``` |
||||
|
||||
|
||||
#### Формат операторов <span id="operator-format"></span> |
||||
|
||||
Формат оператора позволяет задавать произвольные условия в программном стиле. Он имеет следующий вид: |
||||
|
||||
```php |
||||
[operator, operand1, operand2, ...] |
||||
``` |
||||
|
||||
Операнды могут быть заданы в виде строкового формата, формата массива или формата операторов рекурсивно, в то время |
||||
как оператор может быть одним из следующих: |
||||
|
||||
- `and`: операнды должны быть объединены с помощью оператора `AND`. Например, |
||||
`['and', 'id=1', 'id=2']` сгенерирует `id=1 AND id=2`. Если операнд массив, |
||||
он будет сконвертирован в строку по правилам описанным ниже. Например, |
||||
`['and', 'type=1', ['or', 'id=1', 'id=2']]` сгенерирует `type=1 AND (id=1 OR id=2)`. |
||||
Этот метод не производит никакого экранирования. |
||||
|
||||
- `or`: похож на оператор `and` за исключением того, что будет использоваться оператор `OR`. |
||||
|
||||
- `between`: первый операнд должен быть именем столбца, а второй и третий оператор должны быть начальным и конечным |
||||
значением диапазона. Например, `['between', 'id', 1, 10]` сгенерирует `id BETWEEN 1 AND 10`. |
||||
|
||||
- `not between`: похож на `between` за исключением того, что `BETWEEN` заменяется на `NOT BETWEEN` |
||||
в сгенерированном условии. |
||||
|
||||
- `in`: первый операнд должен быть столбцом или выражением БД. Второй операнд может быть либо массивом, либо объектом `Query`. |
||||
Будет сгенерировано условие `IN`. Если второй операнд массив, он будет представлять набор значений, которым может быть |
||||
равен столбец или выражение БД; Если второй операнд объект `Query`, будет сформирован подзапрос, который будет использован |
||||
как диапазон для столбца или выражения БД. Например, `['in', 'id', [1, 2, 3]]` сформирует `id IN (1, 2, 3)`. |
||||
Метод будет правильно экранировать имя столбца и значения диапазона. Оператор `in` также поддерживает составные столбцы. |
||||
В этом случае, первый операнд должен быть массивом названий столбцом, в то время как операнд 2 должен быть массивом |
||||
массивов или объектом `Query` представляющим диапазоны для столбцов. |
||||
|
||||
- `not in`: похож на оператор `in`, кроме того что `IN` будет заменён на `NOT IN` в сформированном условии. |
||||
|
||||
- `like`: первый операнд должен быть столбцом или выражением БД, а второй операнд будет строкой или массивом представляющим |
||||
значения, на которые должны быть похожи столбцы или выражения БД. Например, `['like', 'name', 'tester']` |
||||
сформирует `name LIKE '%tester%'`. |
||||
Когда диапазон значений задан в виде массива, несколько `LIKE` утверждений будут сформированы и соединены с помощью `AND`. |
||||
Например, `['like', 'name', ['test', 'sample']]` сформирует `name LIKE '%test%' AND name LIKE '%sample%'`. |
||||
Вы также можете передать третий необязательный операнд, для указания способа экранирования специальных символов в значениях. |
||||
Операнд должен быть представлен массивом соответствия специальных символов их экранированным аналогам. Если этот |
||||
операнд не задан, то будет использовано соответствие по умолчанию. Вы можете также использовать значение `false` |
||||
или пустой массив, чтоб указать что значения уже экранированы. Обратите внимание, что при использовании массива соответствия |
||||
экранирования (или если третий операнд не передан), значения будут автоматически заключены в символы процентов. |
||||
|
||||
> Примечание: При использовании PostgreSQL вы можете использовать также [`ilike`](http://www.postgresql.org/docs/8.3/static/functions-matching.html#FUNCTIONS-LIKE) |
||||
> вместо `like` для регистронезависимого поиска. |
||||
|
||||
- `or like`: похож на оператор `like`, только утверждения `LIKE` будут объединяться с помощью оператора `OR`, если |
||||
второй операнд будет представлен массивом. |
||||
|
||||
- `not like`: похож на оператор `like`, только `LIKE` будет заменён на `NOT LIKE` в сгенерированном условии. |
||||
|
||||
- `or not like`: похож на оператор `not like`, только утверждения `NOT LIKE` будут объединены с помощью `OR`. |
||||
|
||||
- `exists`: требует один операнд, который должен быть экземпляром [[yii\db\Query]] представляющим подзапрос. Будет |
||||
сгенерировано выражение `EXISTS (sub-query)`. |
||||
|
||||
- `not exists`: похож на оператор `exists` и сформирует выражение `NOT EXISTS (sub-query)`. |
||||
|
||||
- `>`, `<=`, или другие валидные операторы БД, которые требуют двух операндов: первый операнд должен быть именем |
||||
столбца, второй операнд это значение. Например, `['>', 'age', 10]` сформирует `age>10`. |
||||
|
||||
|
||||
#### Добавление условий <span id="appending-conditions"></span> |
||||
|
||||
Вы можете использовать [[yii\db\Query::andWhere()|andWhere()]] или [[yii\db\Query::orWhere()|orWhere()]] для добавления |
||||
дополнительных условий. Вы можете использовать эти вызовы несколько раз для добавления нескольких условий. |
||||
Например: |
||||
|
||||
```php |
||||
$status = 10; |
||||
$search = 'yii'; |
||||
|
||||
$query->where(['status' => $status]); |
||||
|
||||
if (!empty($search)) { |
||||
$query->andWhere(['like', 'title', $search]); |
||||
} |
||||
``` |
||||
|
||||
Если `$search` не пустое, то будет сформировано следующее выражение: |
||||
|
||||
```sql |
||||
... WHERE (`status` = 10) AND (`title` LIKE '%yii%') |
||||
``` |
||||
|
||||
|
||||
#### Условия для фильтров <span id="filter-conditions"></span> |
||||
|
||||
Когда условие `WHERE` формируется на основе пользовательского ввода, обычно хочется проигнорировать не заданные значения. |
||||
Например, в форме поиска, которая позволяет осуществлять поиск по имени пользователя или email, вы хотели бы игнорировать |
||||
username/email условие, если пользователь ничего не ввёл в поле ввода. Вы можете достичь этого используя метод |
||||
[[yii\db\Query::filterWhere()|filterWhere()]]. |
||||
|
||||
```php |
||||
// $username и $email вводит пользователь |
||||
$query->filterWhere([ |
||||
'username' => $username, |
||||
'email' => $email, |
||||
]); |
||||
``` |
||||
|
||||
Единственное отличие между [[yii\db\Query::filterWhere()|filterWhere()]] и [[yii\db\Query::where()|where()]] |
||||
заключается в игнорировании пустых значений переданных в условие в [форме массива](#hash-format). Таким образом |
||||
если `$email` будет пустым, а `$username` нет, то приведённый выше код сформирует `...WHERE username=:username`. |
||||
|
||||
> Информация: значение признаётся пустым, если это null, пустой массив, пустая строка или строка состоящая из одних пробельных символов. |
||||
|
||||
Также вместо [[yii\db\Query::andWhere()|andWhere()]] и [[yii\db\Query::orWhere()|orWhere()]], вы можете использовать |
||||
[[yii\db\Query::andFilterWhere()|andFilterWhere()]] и [[yii\db\Query::orFilterWhere()|orFilterWhere()]] |
||||
для добавления дополнительных условий фильтрации. |
||||
|
||||
|
||||
### [[yii\db\Query::orderBy()|orderBy()]] <span id="order-by"></span> |
||||
|
||||
Метод [[yii\db\Query::orderBy()|orderBy()]] определяет фрагмент `ORDER BY` SQL выражения. Например, |
||||
|
||||
```php |
||||
// ... ORDER BY `id` ASC, `name` DESC |
||||
$query->orderBy([ |
||||
'id' => SORT_ASC, |
||||
'name' => SORT_DESC, |
||||
]); |
||||
``` |
||||
|
||||
В данном коде, ключи массива это имена столбцов, а значения массива это соответствующее направление сортировки. |
||||
PHP константа `SORT_ASC` определяет сортировку по возрастанию и `SORT_DESC` сортировка по умолчанию. |
||||
|
||||
Если `ORDER BY` содержит только простые имена столбцов, вы можете определить их с помощью столбцов, также |
||||
как и при написании обычного SQL. Например, |
||||
|
||||
```php |
||||
$query->orderBy('id ASC, name DESC'); |
||||
``` |
||||
|
||||
> Примечание: Вы должны использовать массив для указания `ORDER BY` содержащих выражения БД. |
||||
|
||||
Вы можете вызывать [[yii\db\Query::addOrderBy()|addOrderBy()]] для добавления столбцов в фрагмент `ORDER BY`. |
||||
|
||||
```php |
||||
$query->orderBy('id ASC') |
||||
->addOrderBy('name DESC'); |
||||
``` |
||||
|
||||
|
||||
### [[yii\db\Query::groupBy()|groupBy()]] <span id="group-by"></span> |
||||
|
||||
Метод [[yii\db\Query::groupBy()|groupBy()]] определяет фрагмент `GROUP BY` SQL запроса. |
||||
|
||||
```php |
||||
// ... GROUP BY `id`, `status` |
||||
$query->groupBy(['id', 'status']); |
||||
``` |
||||
|
||||
Если фрагмент `GROUP BY` содержит только простые имена столбцов, вы можете указать их используя строку, также как в |
||||
обычном SQL. |
||||
|
||||
```php |
||||
$query->groupBy('id, status'); |
||||
``` |
||||
|
||||
> Примечание: Вы должны использовать массив для указания `GROUP BY` содержащих выражения БД. |
||||
|
||||
Вы можете вызывать [[yii\db\Query::addGroupBy()|addGroupBy()]] для добавления имён столбцов в фрагмент `GROUP BY`. |
||||
For example, |
||||
|
||||
```php |
||||
$query->groupBy(['id', 'status']) |
||||
->addGroupBy('age'); |
||||
``` |
||||
|
||||
|
||||
### [[yii\db\Query::having()|having()]] <span id="having"></span> |
||||
|
||||
Метод [[yii\db\Query::having()|having()]] определяет фрагмент `HAVING` SQL запроса. Он принимает условия, которое |
||||
может быть определено тем же способом, что и для [where()](#where). |
||||
|
||||
```php |
||||
// ... HAVING `status` = 1 |
||||
$query->having(['status' => 1]); |
||||
``` |
||||
|
||||
Пожалуйста, обратитесь к документации для [where()](#where) для более подробной информации о определении условий. |
||||
|
||||
Вы можете вызывать [[yii\db\Query::andHaving()|andHaving()]] или [[yii\db\Query::orHaving()|orHaving()]] для добавления |
||||
дополнительных условий в фрагмент `HAVING`. |
||||
|
||||
```php |
||||
// ... HAVING (`status` = 1) AND (`age` > 30) |
||||
$query->having(['status' => 1]) |
||||
->andHaving(['>', 'age', 30]); |
||||
``` |
||||
|
||||
|
||||
### [[yii\db\Query::limit()|limit()]] и [[yii\db\Query::offset()|offset()]] <span id="limit-offset"></span> |
||||
|
||||
Методы [[yii\db\Query::limit()|limit()]] и [[yii\db\Query::offset()|offset()]] определяют фрагменты `LIMIT` |
||||
и `OFFSET` SQL запроса. |
||||
|
||||
```php |
||||
// ... LIMIT 10 OFFSET 20 |
||||
$query->limit(10)->offset(20); |
||||
``` |
||||
|
||||
Если вы определяете неправильный limit или offset (например отрицательное значение), они будут проигнорированы. |
||||
|
||||
> Информация: Для СУБД, которые не поддерживают `LIMIT` и `OFFSET` (такие как MSSQL), построитель запросов будет |
||||
генерировать SQL выражения, которые эмулирует поведение `LIMIT`/`OFFSET`. |
||||
|
||||
|
||||
### [[yii\db\Query::join()|join()]] <span id="join"></span> |
||||
|
||||
Метод [[yii\db\Query::join()|join()]] определяет фрагмент `JOIN` SQL запроса. |
||||
|
||||
```php |
||||
// ... LEFT JOIN `post` ON `post`.`user_id` = `user`.`id` |
||||
$query->join('LEFT JOIN', 'post', 'post.user_id = user.id'); |
||||
``` |
||||
|
||||
Метод [[yii\db\Query::join()|join()]] принимает четыре параметра: |
||||
|
||||
- `$type`: тип объединения, например, `'INNER JOIN'`, `'LEFT JOIN'`. |
||||
- `$table`: имя таблицы, которая должна быть присоединена. |
||||
- `$on`: необязательное условие объединения, то есть фрагмент `ON`. Пожалуйста, обратитесь к документации для |
||||
[where()](#where) для более подробной информации о определении условий. |
||||
- `$params`: необязательные параметры присоединяемые к условию объединения. |
||||
|
||||
Вы можете использовать следующие сокращающие методы для указания `INNER JOIN`, `LEFT JOIN` и `RIGHT JOIN`, в указанном порядке. |
||||
|
||||
- [[yii\db\Query::innerJoin()|innerJoin()]] |
||||
- [[yii\db\Query::leftJoin()|leftJoin()]] |
||||
- [[yii\db\Query::rightJoin()|rightJoin()]] |
||||
|
||||
Например, |
||||
|
||||
```php |
||||
$query->leftJoin('post', 'post.user_id = user.id'); |
||||
``` |
||||
|
||||
Для соединения с несколькими таблицами, вызовите вышеуказанные методы несколько раз. |
||||
|
||||
Кроме соединения с таблицами, вы можете также присоединять подзапросы. Чтоб это сделать, укажите объединяемый подзапрос |
||||
как объект [[yii\db\Query]]. |
||||
|
||||
```php |
||||
$subQuery = (new \yii\db\Query())->from('post'); |
||||
$query->leftJoin(['u' => $subQuery], 'u.id = author_id'); |
||||
``` |
||||
|
||||
В этом случае, вы должны передать подзапросы в массиве и использовать ключи для определения алиасов. |
||||
|
||||
|
||||
### [[yii\db\Query::union()|union()]] <span id="union"></span> |
||||
|
||||
Метод [[yii\db\Query::union()|union()]] определяет фрагмент `UNION` SQL запроса. |
||||
|
||||
```php |
||||
$query1 = (new \yii\db\Query()) |
||||
->select("id, category_id AS type, name") |
||||
->from('post') |
||||
->limit(10); |
||||
|
||||
$query2 = (new \yii\db\Query()) |
||||
->select('id, type, name') |
||||
->from('user') |
||||
->limit(10); |
||||
|
||||
$query1->union($query2); |
||||
``` |
||||
|
||||
Вы можете вызвать [[yii\db\Query::union()|union()]] несколько раз для присоединения фрагментов `UNION`. |
||||
|
||||
|
||||
## Методы выборки <span id="query-methods"></span> |
||||
|
||||
[[yii\db\Query]] предоставляет целый набор методов для разных вариантов выборки: |
||||
|
||||
- [[yii\db\Query::all()|all()]]: возвращает массив строк, каждая из которых это ассоциативный массив пар ключ-значение. |
||||
- [[yii\db\Query::one()|one()]]: возвращает первую строку запроса. |
||||
- [[yii\db\Query::column()|column()]]: возвращает первый столбец результата. |
||||
- [[yii\db\Query::scalar()|scalar()]]: возвращает скалярное значение первого столбца первой строки результата. |
||||
- [[yii\db\Query::exists()|exists()]]: возвращает значение указывающее, что выборка содержит результат. |
||||
- [[yii\db\Query::count()|count()]]: возвращает результат `COUNT` запроса. |
||||
- Другие методы агрегирования запросов, включая [[yii\db\Query::sum()|sum($q)]], [[yii\db\Query::average()|average($q)]], |
||||
[[yii\db\Query::max()|max($q)]], [[yii\db\Query::min()|min($q)]]. Параметр `$q` обязателен для этих методов и могут |
||||
содержать либо имя столбца, либо выражение БД. |
||||
|
||||
Например: |
||||
|
||||
```php |
||||
// SELECT `id`, `email` FROM `user` |
||||
$rows = (new \yii\db\Query()) |
||||
->select(['id', 'email']) |
||||
->from('user') |
||||
->all(); |
||||
|
||||
// SELECT * FROM `user` WHERE `username` LIKE `%test%` |
||||
$row = (new \yii\db\Query()) |
||||
->from('user') |
||||
->where(['like', 'username', 'test']) |
||||
->one(); |
||||
``` |
||||
|
||||
> Примечание: метод [[yii\db\Query::one()|one()]] вернёт только первую строку результата запроса. Он НЕ добавляет |
||||
`LIMIT 1` в генерируемый SQL. Это хорошо и предпочтительно если вы знаете, что запрос вернёт только одну или несколько |
||||
строк данных (например, при запросе по первичному ключу). Однако, если запрос потенциально может вернут много |
||||
строк данных, вы должны вызвать `limit(1)` для повышения производительности, Например: |
||||
`(new \yii\db\Query())->from('user')->limit(1)->one()`. |
||||
|
||||
Все методы выборки могут получать необязательный параметр `$db`, представляющий [[yii\db\Connection|соединение с БД]], |
||||
которое должно использоваться, чтобы выполнить запрос к БД. Если вы упускаете этот параметр, будет использоваться |
||||
[компонент приложения](structure-application-components.md) `$db`. Ниже приведён ещё один пример использования метода |
||||
`count()`: |
||||
|
||||
```php |
||||
// executes SQL: SELECT COUNT(*) FROM `user` WHERE `last_name`=:last_name |
||||
$count = (new \yii\db\Query()) |
||||
->from('user') |
||||
->where(['last_name' => 'Smith']) |
||||
->count(); |
||||
``` |
||||
|
||||
При вызове методов выборки [[yii\db\Query]], внутри на самом деле проводится следующая работа: |
||||
|
||||
* Вызывается [[yii\db\QueryBuilder]] для генерации SQL запроса на основе текущего [[yii\db\Query]]; |
||||
* Создаёт объект [[yii\db\Command]] с сгенерированным SQL запросом; |
||||
* Вызывается выбирающий метод (например `queryAll()`) из [[yii\db\Command]] для выполнения SQL запроса и извлечения данных. |
||||
|
||||
Иногда вы можете захотеть увидеть или использовать SQL запрос построенный из объекта [[yii\db\Query]]. Этой цели можно |
||||
добиться с помощью следующего кода: |
||||
|
||||
```php |
||||
$command = (new \yii\db\Query()) |
||||
->select(['id', 'email']) |
||||
->from('user') |
||||
->where(['last_name' => 'Smith']) |
||||
->limit(10) |
||||
->createCommand(); |
||||
|
||||
// показать SQL запрос |
||||
echo $command->sql; |
||||
// показать привязываемые параметры |
||||
print_r($command->params); |
||||
|
||||
// возвращает все строки запроса |
||||
$rows = $command->queryAll(); |
||||
``` |
||||
|
||||
|
||||
### Индексация результатов запроса <span id="indexing-query-results"></span> |
||||
|
||||
При вызове [[yii\db\Query::all()|all()]] возвращается массив строк индексированный последовательными целыми числами. |
||||
Иногда вам может потребоваться индексировать его по другому, например сделать индекс по указанному столбцу или |
||||
значением выражения. Вы можете реализовать такое поведение через вызов [[yii\db\Query::indexBy()|indexBy()]] перед |
||||
вызовом [[yii\db\Query::all()|all()]]. |
||||
|
||||
```php |
||||
// возвращает [100 => ['id' => 100, 'username' => '...', ...], 101 => [...], 103 => [...], ...] |
||||
$query = (new \yii\db\Query()) |
||||
->from('user') |
||||
->limit(10) |
||||
->indexBy('id') |
||||
->all(); |
||||
``` |
||||
|
||||
Для индексации по значению выражения, передайте анонимную функцию в метод [[yii\db\Query::indexBy()|indexBy()]]: |
||||
|
||||
```php |
||||
$query = (new \yii\db\Query()) |
||||
->from('user') |
||||
->indexBy(function ($row) { |
||||
return $row['id'] . $row['username']; |
||||
})->all(); |
||||
``` |
||||
|
||||
Анонимная функция должна принимать параметр `$row`, который содержит текущую строку запроса и должна вернуть скалярное |
||||
значение, которое будет использоваться как значение индекса для текущей строки. |
||||
|
||||
|
||||
### Пакетная выборка <span id="batch-query"></span> |
||||
|
||||
При работе с большими объемами данных, методы на подобие [[yii\db\Query::all()]] не подходят, потому что они требуют |
||||
загрузки всех данных в память. Чтобы сохранить требования к памяти минимальными, Yii предоставляет поддержку |
||||
так называемых пакетных выборок. Пакетная выборка делает возможным курсоры данных и выборку данных пакетами. |
||||
|
||||
Пакетная выборка может использоваться следующим образом: |
||||
|
||||
```php |
||||
use yii\db\Query; |
||||
|
||||
$query = (new Query()) |
||||
->from('user') |
||||
->orderBy('id'); |
||||
|
||||
foreach ($query->batch() as $users) { |
||||
// $users это массив из 100 или менее строк из таблицы пользователей |
||||
} |
||||
|
||||
// или если вы хотите перебрать все строки по одной |
||||
foreach ($query->each() as $user) { |
||||
// $user представляет одну строку из выборки |
||||
} |
||||
``` |
||||
|
||||
Метод [[yii\db\Query::batch()]] и [[yii\db\Query::each()]] возвращает объект [[yii\db\BatchQueryResult]], который |
||||
реализует интерфейс `Iterator` и может использоваться в конструкции `foreach`. Во время первой итерации будет выполнен |
||||
SQL запрос к базе данных. Данные будут выбираться пакетами в следующих итерациях. По умолчанию, размер пакета имеет |
||||
размер 100, то есть при каждой выборке будет выбираться по 100 строк. Вы можете изменить размер пакета, передав |
||||
первый параметр в метод `batch()` или `each()`. |
||||
|
||||
По сравнению с [[yii\db\Query::all()]], пакетная выборка загружает только по 100 строк данных за раз в память. |
||||
Если вы обрабатываете данные и затем сразу выбрасываете их, пакетная выборка может помочь уменьшить использование памяти. |
||||
|
||||
Если указать индексный столбец через [[yii\db\Query::indexBy()]], в пакетной выборке индекс будет сохранятся. |
||||
Например, |
||||
|
||||
```php |
||||
$query = (new \yii\db\Query()) |
||||
->from('user') |
||||
->indexBy('username'); |
||||
|
||||
foreach ($query->batch() as $users) { |
||||
// $users индексируется по столбцу "username" |
||||
} |
||||
|
||||
foreach ($query->each() as $username => $user) { |
||||
} |
||||
``` |
@ -0,0 +1,177 @@
|
||||
Url хелпер |
||||
========== |
||||
|
||||
Url хелпер предоставляет набор статических методов для управления URL. |
||||
|
||||
|
||||
## Получение общих URL <span id="getting-common-urls"></span> |
||||
|
||||
Вы можете использовать два метода получения общих URL: домашний URL (Home) и базовый URL (Base) текущего запроса. |
||||
Используйте следующий код, чтобы получить домашний URL: |
||||
|
||||
```php |
||||
$relativeHomeUrl = Url::home(); |
||||
$absoluteHomeUrl = Url::home(true); |
||||
$httpsAbsoluteHomeUrl = Url::home('https'); |
||||
``` |
||||
|
||||
Если вы не передали параметров, то получите относительный URL. Вы можете передать `true`, чтобы получить абсолютный URL |
||||
для текущего протокола или явно указать протокол (`https`, `http`). |
||||
|
||||
Чтобы получить базовый URL текущего запроса: |
||||
|
||||
```php |
||||
$relativeBaseUrl = Url::base(); |
||||
$absoluteBaseUrl = Url::base(true); |
||||
$httpsAbsoluteBaseUrl = Url::base('https'); |
||||
``` |
||||
|
||||
Единственный параметр данного метода работает также как и `Url::home()`. |
||||
|
||||
## Создание URL <span id="creating-urls"></span> |
||||
|
||||
Чтобы создать URL для соответствующего роута используйте метод `Url::toRoute()`. Метод использует [[\yii\web\UrlManager]]. |
||||
Для того чтобы создать URL: |
||||
|
||||
```php |
||||
$url = Url::toRoute(['product/view', 'id' => 42]); |
||||
``` |
||||
|
||||
Вы можете задать роут строкой, например, `site/index`. А также вы можете использовать массив, если хотите задать |
||||
дополнительные параметры запроса для URL. Формат массива должен быть следующим: |
||||
|
||||
```php |
||||
// сгенерирует: /index.php?r=site/index¶m1=value1¶m2=value2 |
||||
['site/index', 'param1' => 'value1', 'param2' => 'value2'] |
||||
``` |
||||
|
||||
Если вы хотите создать URL с якорем, то вы можете использовать параметр массива с ключом `#`. Например: |
||||
|
||||
```php |
||||
// сгенерирует: /index.php?r=site/index¶m1=value1#name |
||||
['site/index', 'param1' => 'value1', '#' => 'name'] |
||||
``` |
||||
|
||||
Роут может быть и абсолютным, и относительным. Абсолютный URL начинается со слеша (например, `/site/index`), |
||||
относительный - без (например, `site/index` or `index`). Относительный URL будет сконвертирован в абсолютный по следующим |
||||
правилам: |
||||
|
||||
- Если роут пустая строка, то будет использовано текущее значение [[\yii\web\Controller::route|route]]; |
||||
- Если роут не содержит слешей (например, `index`), то он будет считаться экшеном текущего контролера и будет определен |
||||
с помощью [[\yii\web\Controller::uniqueId]]; |
||||
- Если роут начинается не со слеша (например, `site/index`), то он будет считаться относительным роутом текущего модуля |
||||
и будет определен с помощью [[\yii\base\Module::uniqueId|uniqueId]]. |
||||
|
||||
Начиная с версии 2.0.2, вы можете задавать роуты с помощью [псевдонимов](concept-aliases.md). В этом случае, сначала |
||||
псевдоним будет сконвертирован в соответствующий роут, который будет преобразован в абсолютный в соответствии с вышеописанными |
||||
правилами. |
||||
|
||||
Примеры использования метода: |
||||
|
||||
```php |
||||
// /index.php?r=site/index |
||||
echo Url::toRoute('site/index'); |
||||
|
||||
// /index.php?r=site/index&src=ref1#name |
||||
echo Url::toRoute(['site/index', 'src' => 'ref1', '#' => 'name']); |
||||
|
||||
// /index.php?r=post/edit&id=100 псевдоним "@postEdit" задан как "post/edit" |
||||
echo Url::toRoute(['@postEdit', 'id' => 100]); |
||||
|
||||
// http://www.example.com/index.php?r=site/index |
||||
echo Url::toRoute('site/index', true); |
||||
|
||||
// https://www.example.com/index.php?r=site/index |
||||
echo Url::toRoute('site/index', 'https'); |
||||
``` |
||||
|
||||
Другой метод `Url::to()` очень похож на [[toRoute()]]. Единственное отличие: входным параметром должен быть массив. |
||||
Если будет передана строка, то она будет воспринята как URL. |
||||
|
||||
Первый аргумент может быть: |
||||
|
||||
- массивом: будет вызван [[toRoute()]], чтобы сгенерировать URL. Например: `['site/index']`, `['post/index', 'page' => 2]`. |
||||
В разделе [[toRoute()]] подробно описано как задавать роут; |
||||
- Строка, начинающаяся с `@`, будет обработана как псевдоним. Будет возвращено соответствующее значение псевдонима; |
||||
- Пустая строка: вернет текущий URL; |
||||
- Обычная строка: вернет строку без изменений |
||||
|
||||
Когда у метода задан второй параметр `$scheme` (строка или true), то сгенерированный URL будет с протоколом |
||||
(полученным из [[\yii\web\UrlManager::hostInfo]]). Если в `$url` указан протокол, то его значение будет заменено. |
||||
|
||||
Пример использования: |
||||
|
||||
```php |
||||
// /index.php?r=site/index |
||||
echo Url::to(['site/index']); |
||||
|
||||
// /index.php?r=site/index&src=ref1#name |
||||
echo Url::to(['site/index', 'src' => 'ref1', '#' => 'name']); |
||||
|
||||
// /index.php?r=post/edit&id=100 псевдоним "@postEdit" задан как "post/edit" |
||||
echo Url::to(['@postEdit', 'id' => 100]); |
||||
|
||||
// Текущий URL |
||||
echo Url::to(); |
||||
|
||||
// /images/logo.gif |
||||
echo Url::to('@web/images/logo.gif'); |
||||
|
||||
// images/logo.gif |
||||
echo Url::to('images/logo.gif'); |
||||
|
||||
// http://www.example.com/images/logo.gif |
||||
echo Url::to('@web/images/logo.gif', true); |
||||
|
||||
// https://www.example.com/images/logo.gif |
||||
echo Url::to('@web/images/logo.gif', 'https'); |
||||
``` |
||||
|
||||
Начиная с версии 2.0.3, вы можете использовать [[yii\helpers\Url::current()]], чтобы создавать URL на основе текущего |
||||
запрошенного роута и его GET-параметров. Вы можете изменить, удалить или добавить новые GET-параметры передав в метод |
||||
параметр `$params`. Например: |
||||
|
||||
```php |
||||
// предположим $_GET = ['id' => 123, 'src' => 'google'], а текущий роут "post/view" |
||||
|
||||
// /index.php?r=post/view&id=123&src=google |
||||
echo Url::current(); |
||||
|
||||
// /index.php?r=post/view&id=123 |
||||
echo Url::current(['src' => null]); |
||||
// /index.php?r=post/view&id=100&src=google |
||||
echo Url::current(['id' => 100]); |
||||
``` |
||||
|
||||
|
||||
## Запоминание URL <span id="remember-urls"></span> |
||||
|
||||
Существуют задачи, когда вам необходимо запомнить URL и потом использовать его в процессе одного или нескольких |
||||
последовательных запросов. Это может быть достигнуто следующим образом: |
||||
|
||||
```php |
||||
// Запомнить текущий URL |
||||
Url::remember(); |
||||
|
||||
// Запомнить определенный URL. Входные параметры смотрите на примере Url::to(). |
||||
Url::remember(['product/view', 'id' => 42]); |
||||
|
||||
// Запомнить URL под определенным именем |
||||
Url::remember(['product/view', 'id' => 42], 'product'); |
||||
``` |
||||
|
||||
В следующем запросе мы можем получить сохраненный URL следующим образом: |
||||
|
||||
```php |
||||
$url = Url::previous(); |
||||
$productUrl = Url::previous('product'); |
||||
``` |
||||
|
||||
## Проверить относительность URL <span id="checking-relative-urls"></span> |
||||
|
||||
Чтобы проверить относительный URL или нет (например, если в нем не содержится информации о хосте), вы можете использовать |
||||
следующий код: |
||||
|
||||
```php |
||||
$isRelative = Url::isRelative('test/it'); |
||||
``` |
@ -0,0 +1,368 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd"> |
||||
<!--Created by yEd 3.12.2--> |
||||
<key for="graphml" id="d0" yfiles.type="resources"/> |
||||
<key for="port" id="d1" yfiles.type="portgraphics"/> |
||||
<key for="port" id="d2" yfiles.type="portgeometry"/> |
||||
<key for="port" id="d3" yfiles.type="portuserdata"/> |
||||
<key attr.name="url" attr.type="string" for="node" id="d4"/> |
||||
<key attr.name="description" attr.type="string" for="node" id="d5"/> |
||||
<key for="node" id="d6" yfiles.type="nodegraphics"/> |
||||
<key attr.name="Description" attr.type="string" for="graph" id="d7"/> |
||||
<key attr.name="url" attr.type="string" for="edge" id="d8"/> |
||||
<key attr.name="description" attr.type="string" for="edge" id="d9"/> |
||||
<key for="edge" id="d10" yfiles.type="edgegraphics"/> |
||||
<graph edgedefault="directed" id="G"> |
||||
<data key="d7"/> |
||||
<node id="n0"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="69.0" width="103.0" x="34.0" y="-11.5"/> |
||||
<y:Fill color="#ADF4A6" transparent="false"/> |
||||
<y:BorderStyle color="#FF0000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="36.68359375" x="33.158203125" y="25.1494140625">admin<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<node id="n1"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="69.0" width="103.0" x="193.0" y="-11.5"/> |
||||
<y:Fill color="#ADF4A6" transparent="false"/> |
||||
<y:BorderStyle color="#FF0000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="38.025390625" x="32.4873046875" y="25.1494140625">author<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<node id="n2"> |
||||
<data key="d6"> |
||||
<y:SVGNode> |
||||
<y:Geometry height="64.53585815429688" width="56.560157775878906" x="216.21992111206055" y="-132.03585815429688"/> |
||||
<y:Fill color="#CCCCFF" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.905467987060547" y="-27.814727783203125">John, ID=2<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.113555908203125" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:SVGNodeProperties usingVisualBounds="true"/> |
||||
<y:SVGModel svgBoundsPolicy="0"> |
||||
<y:SVGContent refid="1"/> |
||||
</y:SVGModel> |
||||
</y:SVGNode> |
||||
</data> |
||||
</node> |
||||
<node id="n3"> |
||||
<data key="d6"> |
||||
<y:SVGNode> |
||||
<y:Geometry height="66.76200103759766" width="56.554100036621094" x="57.22294998168945" y="-133.14892959594727"/> |
||||
<y:Fill color="#CCCCFF" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.908496856689453" y="-27.701656341552734">Jane, ID=1<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.000484466552734" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:SVGNodeProperties usingVisualBounds="true"/> |
||||
<y:SVGModel svgBoundsPolicy="0"> |
||||
<y:SVGContent refid="2"/> |
||||
</y:SVGModel> |
||||
</y:SVGNode> |
||||
</data> |
||||
</node> |
||||
<node id="n4"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="69.0" width="103.0" x="34.0" y="197.5"/> |
||||
<y:Fill color="#99CCFF" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.71484375" x="19.142578125" y="25.1494140625">updatePost<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<node id="n5"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="69.0" width="103.0" x="193.0" y="197.5"/> |
||||
<y:Fill color="#99CCFF" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="89.388671875" x="6.8056640625" y="25.1494140625">updateOwnPost<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<node id="n6"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="69.0" width="103.0" x="352.0" y="197.5"/> |
||||
<y:Fill color="#99CCFF" transparent="false"/> |
||||
<y:BorderStyle color="#FF0000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="61.36328125" x="20.818359375" y="25.1494140625">createPost<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<node id="n7"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="29.535858154296875" width="103.0" x="193.0" y="167.96414184570312"/> |
||||
<y:Fill color="#FFCC00" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.03515625" x="19.482421875" y="5.4173431396484375">AuthorRule<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<edge id="e0" source="n4" target="n0"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#000000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e1" source="n4" target="n5"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#000000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e2" source="n1" target="n0"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#FF0000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e3" source="n6" target="n1"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"> |
||||
<y:Point x="403.5" y="23.0"/> |
||||
</y:Path> |
||||
<y:LineStyle color="#FF0000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e4" source="n1" target="n2"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#000000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e5" source="n0" target="n3"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#FF0000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e6" source="n7" target="n1"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#000000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
</graph> |
||||
<data key="d0"> |
||||
<y:Resources> |
||||
<y:Resource id="1"><?xml version="1.0" encoding="utf-8"?> |
||||
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" |
||||
width="57px" height="65px" viewBox="0 0 57 65" enable-background="new 0 0 57 65" xml:space="preserve"> |
||||
<g> |
||||
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"> |
||||
<stop offset="0.2711" style="stop-color:#FFAB4F"/> |
||||
<stop offset="1" style="stop-color:#FFD28F"/> |
||||
</linearGradient> |
||||
<path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109 |
||||
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77 |
||||
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/> |
||||
<path id="body_18_" fill="#ECECEC" stroke="#9B9B9B" stroke-miterlimit="10" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51 |
||||
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-11.244-6.146-11.244-6.146 |
||||
c-1.771,1.655-5.61,3.802-10.063,3.802c-4.453,0-8.292-2.146-10.063-3.802c0,0-5.755,0.586-11.189,6.021 |
||||
C1.378,56.689,0.5,62.768,0.5,62.768z"/> |
||||
|
||||
<radialGradient id="SVGID_2_" cx="22.6621" cy="21.707" r="17.7954" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_2_)" stroke="#E55E03" d="M28.106,33.486c-8.112,0-12.688,4.313-12.688,10.438 |
||||
c0,7.422,12.688,10.438,12.688,10.438s14.688-3.016,14.688-10.438C42.793,38.75,36.215,33.486,28.106,33.486z M26.288,53.051 |
||||
c0,0-7.135-2.093-8.805-7.201c-0.222-0.682,0.147-1.156,0.795-1.521V37.8h20.188v6.663c0.235,0.352,1.109,0.737,1.229,1.387 |
||||
C40.445,49.917,26.288,53.051,26.288,53.051z"/> |
||||
|
||||
<radialGradient id="SVGID_3_" cx="15.2056" cy="831.1875" r="32.3071" gradientTransform="matrix(1 0 0 1 0.0801 -773.6914)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_3_)" stroke="#E55E03" d="M49.529,51.225c-2.239-2.24-5.041-3.724-7.396-4.67 |
||||
c-2.854,5.51-14.021,7.807-14.021,7.807s-10.472-2.483-12.387-8.514c-2.439,0.771-5.787,2.287-8.749,5.25 |
||||
c-5.592,5.592-6.47,11.67-6.47,11.67c0,1.938,1.575,3.492,3.523,3.492h48.51c1.946,0,3.521-1.558,3.521-3.492 |
||||
C56.055,62.768,54.211,55.906,49.529,51.225z"/> |
||||
|
||||
<radialGradient id="SVGID_4_" cx="17.0723" cy="18.4907" r="11.8931" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_4_)" stroke="#E55E03" d="M13.404,44.173c1.15-1.81,2.039-3.832,3.332-5.397 |
||||
c-0.514,1.027-1.669,4.084-1.669,5.148c0,5.186,10.366,9.079,14.688,10.438c-3.472,1.627-9.134-1.498-11.334-2.359 |
||||
c-3.601-1.419-4.071-3.063-5.89-4.854C12.523,47.135,12.878,45,13.404,44.173z"/> |
||||
|
||||
<radialGradient id="SVGID_5_" cx="31.8184" cy="19.3525" r="14.63" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_5_)" stroke="#E55E03" d="M45.777,43.924c-1.317-1.568-5.11-9.424-6.604-6.617 |
||||
c0.516,1.025,3.617,3.693,3.617,6.617c0,5.186-10.271,8.576-16.699,9.145c1.429,4.938,11.373,1.293,13.805-0.313 |
||||
c3.563-2.354,4.563-5.133,7.854-3.705C47.754,49.045,48.006,46.574,45.777,43.924z"/> |
||||
|
||||
<radialGradient id="SVGID_6_" cx="30.4893" cy="4.8721" r="5.2028" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_6_)" stroke="#E55E03" d="M30.777,54.167c0.357,0.836-0.153,1.983-0.352,2.813 |
||||
c-0.256,1.084-0.072,2.104,0.102,3.186c0.164,1.02,0.156,2.107,0.25,3.167c0.082,0.916,0.482,1.849,0.357,2.75"/> |
||||
|
||||
<radialGradient id="SVGID_7_" cx="23.2871" cy="5.3008" r="5.5143" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_7_)" stroke="#E55E03" d="M23.695,53.417c-0.508,0.584-0.476,2.209-0.398,3 |
||||
c0.116,1.183,0.456,2.099,0.333,3.333c-0.192,1.943,0.154,4.479-0.436,6.333"/> |
||||
|
||||
<radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FFD28F"/> |
||||
<stop offset="1" style="stop-color:#FFAB4F"/> |
||||
</radialGradient> |
||||
<path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357 |
||||
c0.086,10.2-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012 |
||||
C36.627,4.945,43.59,13.158,43.676,23.357z"/> |
||||
|
||||
<linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.501" y1="-12291.5195" x2="6492.1304" y2="-12384.9688" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3351.7349)"> |
||||
<stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/> |
||||
<stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/> |
||||
</linearGradient> |
||||
<path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386 |
||||
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247 |
||||
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/> |
||||
<path id="Hair_Young_Black_1_" fill="#5C5C5C" stroke="#353535" stroke-linecap="round" stroke-linejoin="round" d="M20.278,13.25 |
||||
c3.417,4.333,9.333,6.917,9.333,6.917l-1.417-3.5c0,0,7.094,4.691,8.083,4.333c0.968-0.2-1.082-3.807-1.082-3.807 |
||||
s3.138,1.795,4.854,3.969c1.803,2.28,4.285,3.504,4.285,3.504S47.027,2.719,27.289,2.744C8.278,2.709,12.058,27.678,12.058,27.678 |
||||
L14.695,17c0,0,0.914,5.757,1.399,4.875C17.861,15.211,18.861,11.5,20.278,13.25z"/> |
||||
</g> |
||||
</svg> |
||||
</y:Resource> |
||||
<y:Resource id="2"><?xml version="1.0" encoding="utf-8"?> |
||||
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" |
||||
width="57px" height="67px" viewBox="0 0 57 67" enable-background="new 0 0 57 67" xml:space="preserve"> |
||||
<g> |
||||
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"> |
||||
<stop offset="0.2711" style="stop-color:#FFAB4F"/> |
||||
<stop offset="1" style="stop-color:#FFD28F"/> |
||||
</linearGradient> |
||||
<path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109 |
||||
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77 |
||||
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/> |
||||
|
||||
<radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FFD28F"/> |
||||
<stop offset="1" style="stop-color:#FFAB4F"/> |
||||
</radialGradient> |
||||
<path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357 |
||||
c0.086,10.199-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012 |
||||
C36.627,4.945,43.59,13.158,43.676,23.357z"/> |
||||
|
||||
<linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.5" y1="-12286.8594" x2="6492.1294" y2="-12380.3086" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3350.4617)"> |
||||
<stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/> |
||||
<stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/> |
||||
</linearGradient> |
||||
<path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386 |
||||
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247 |
||||
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/> |
||||
<path id="Hair_Female_1_Red_1_" fill="#FAE1AA" stroke="#E2B354" stroke-linecap="round" stroke-linejoin="round" d="M28.372,0.5 |
||||
C17.537,0.5,8.269,7.748,9.153,26.125c0.563,6.563,5.862,12.042,9.366,13.531c-2.929-10.968-0.304-25.021-0.585-25.526 |
||||
c-0.281-0.505,3.536,6.728,3.536,6.728l3.183-8.312c5.541,4.28,0.393,11.309,1.049,11.058c4.26-1.631,5.34-9.228,5.34-9.228 |
||||
s2.729,3.657,2.701,5.504c-0.054,3.562,2.194-6.067,2.194-6.067l1.027,2.031c6.727,9.822,3.684,16.208,1.648,22.781 |
||||
c15.666-0.703,12.291-10.48,9.66-18.407C43.59,6.092,39.206,0.5,28.372,0.5z"/> |
||||
|
||||
<linearGradient id="body_1_" gradientUnits="userSpaceOnUse" x1="95.9063" y1="-3134.2153" x2="31.5133" y2="-3134.2153" gradientTransform="matrix(0.9852 0 0 -0.9852 -34.4844 -3031.9851)"> |
||||
<stop offset="0" style="stop-color:#49AD33"/> |
||||
<stop offset="1" style="stop-color:#C2DA92"/> |
||||
</linearGradient> |
||||
<path id="body_8_" fill="url(#body_1_)" stroke="#008D33" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51 |
||||
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-8.244-5.146-8.244-5.146 |
||||
c-1.444,6.983-8.555,8.786-13.007,8.786s-11.322-2.643-11.941-9.439c0,0-4.559,1.199-9.367,5.674 |
||||
C1.378,56.689,0.5,62.768,0.5,62.768z"/> |
||||
</g> |
||||
</svg> |
||||
</y:Resource> |
||||
</y:Resources> |
||||
</data> |
||||
</graphml> |
After Width: | Height: | Size: 19 KiB |
@ -0,0 +1,368 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd"> |
||||
<!--Created by yEd 3.12.2--> |
||||
<key for="graphml" id="d0" yfiles.type="resources"/> |
||||
<key for="port" id="d1" yfiles.type="portgraphics"/> |
||||
<key for="port" id="d2" yfiles.type="portgeometry"/> |
||||
<key for="port" id="d3" yfiles.type="portuserdata"/> |
||||
<key attr.name="url" attr.type="string" for="node" id="d4"/> |
||||
<key attr.name="description" attr.type="string" for="node" id="d5"/> |
||||
<key for="node" id="d6" yfiles.type="nodegraphics"/> |
||||
<key attr.name="Description" attr.type="string" for="graph" id="d7"/> |
||||
<key attr.name="url" attr.type="string" for="edge" id="d8"/> |
||||
<key attr.name="description" attr.type="string" for="edge" id="d9"/> |
||||
<key for="edge" id="d10" yfiles.type="edgegraphics"/> |
||||
<graph edgedefault="directed" id="G"> |
||||
<data key="d7"/> |
||||
<node id="n0"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="69.0" width="103.0" x="34.0" y="-11.5"/> |
||||
<y:Fill color="#ADF4A6" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="36.68359375" x="33.158203125" y="25.1494140625">admin<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<node id="n1"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="69.0" width="103.0" x="193.0" y="-11.5"/> |
||||
<y:Fill color="#ADF4A6" transparent="false"/> |
||||
<y:BorderStyle color="#FF0000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="38.025390625" x="32.4873046875" y="25.1494140625">author<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<node id="n2"> |
||||
<data key="d6"> |
||||
<y:SVGNode> |
||||
<y:Geometry height="64.53585815429688" width="56.560157775878906" x="216.21992111206055" y="-132.03585815429688"/> |
||||
<y:Fill color="#CCCCFF" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.905467987060547" y="-27.814727783203125">John, ID=2<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.113555908203125" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:SVGNodeProperties usingVisualBounds="true"/> |
||||
<y:SVGModel svgBoundsPolicy="0"> |
||||
<y:SVGContent refid="1"/> |
||||
</y:SVGModel> |
||||
</y:SVGNode> |
||||
</data> |
||||
</node> |
||||
<node id="n3"> |
||||
<data key="d6"> |
||||
<y:SVGNode> |
||||
<y:Geometry height="66.76200103759766" width="56.554100036621094" x="57.22294998168945" y="-133.14892959594727"/> |
||||
<y:Fill color="#CCCCFF" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.908496856689453" y="-27.701656341552734">Jane, ID=1<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.000484466552734" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:SVGNodeProperties usingVisualBounds="true"/> |
||||
<y:SVGModel svgBoundsPolicy="0"> |
||||
<y:SVGContent refid="2"/> |
||||
</y:SVGModel> |
||||
</y:SVGNode> |
||||
</data> |
||||
</node> |
||||
<node id="n4"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="69.0" width="103.0" x="34.0" y="197.5"/> |
||||
<y:Fill color="#99CCFF" transparent="false"/> |
||||
<y:BorderStyle color="#FF0000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.71484375" x="19.142578125" y="25.1494140625">updatePost<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<node id="n5"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="69.0" width="103.0" x="193.0" y="197.5"/> |
||||
<y:Fill color="#99CCFF" transparent="false"/> |
||||
<y:BorderStyle color="#FF0000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="89.388671875" x="6.8056640625" y="25.1494140625">updateOwnPost<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<node id="n6"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="69.0" width="103.0" x="352.0" y="197.5"/> |
||||
<y:Fill color="#99CCFF" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="61.36328125" x="20.818359375" y="25.1494140625">createPost<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<node id="n7"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="29.535858154296875" width="103.0" x="193.0" y="167.96414184570312"/> |
||||
<y:Fill color="#FFCC00" transparent="false"/> |
||||
<y:BorderStyle color="#FF0000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.03515625" x="19.482421875" y="5.4173431396484375">AuthorRule<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<edge id="e0" source="n4" target="n0"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#000000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e1" source="n4" target="n5"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#FF0000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e2" source="n1" target="n0"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#000000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e3" source="n6" target="n1"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"> |
||||
<y:Point x="403.5" y="23.0"/> |
||||
</y:Path> |
||||
<y:LineStyle color="#000000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e4" source="n1" target="n2"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#FF0000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e5" source="n0" target="n3"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#000000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e6" source="n7" target="n1"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#FF0000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
</graph> |
||||
<data key="d0"> |
||||
<y:Resources> |
||||
<y:Resource id="1"><?xml version="1.0" encoding="utf-8"?> |
||||
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" |
||||
width="57px" height="65px" viewBox="0 0 57 65" enable-background="new 0 0 57 65" xml:space="preserve"> |
||||
<g> |
||||
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"> |
||||
<stop offset="0.2711" style="stop-color:#FFAB4F"/> |
||||
<stop offset="1" style="stop-color:#FFD28F"/> |
||||
</linearGradient> |
||||
<path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109 |
||||
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77 |
||||
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/> |
||||
<path id="body_18_" fill="#ECECEC" stroke="#9B9B9B" stroke-miterlimit="10" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51 |
||||
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-11.244-6.146-11.244-6.146 |
||||
c-1.771,1.655-5.61,3.802-10.063,3.802c-4.453,0-8.292-2.146-10.063-3.802c0,0-5.755,0.586-11.189,6.021 |
||||
C1.378,56.689,0.5,62.768,0.5,62.768z"/> |
||||
|
||||
<radialGradient id="SVGID_2_" cx="22.6621" cy="21.707" r="17.7954" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_2_)" stroke="#E55E03" d="M28.106,33.486c-8.112,0-12.688,4.313-12.688,10.438 |
||||
c0,7.422,12.688,10.438,12.688,10.438s14.688-3.016,14.688-10.438C42.793,38.75,36.215,33.486,28.106,33.486z M26.288,53.051 |
||||
c0,0-7.135-2.093-8.805-7.201c-0.222-0.682,0.147-1.156,0.795-1.521V37.8h20.188v6.663c0.235,0.352,1.109,0.737,1.229,1.387 |
||||
C40.445,49.917,26.288,53.051,26.288,53.051z"/> |
||||
|
||||
<radialGradient id="SVGID_3_" cx="15.2056" cy="831.1875" r="32.3071" gradientTransform="matrix(1 0 0 1 0.0801 -773.6914)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_3_)" stroke="#E55E03" d="M49.529,51.225c-2.239-2.24-5.041-3.724-7.396-4.67 |
||||
c-2.854,5.51-14.021,7.807-14.021,7.807s-10.472-2.483-12.387-8.514c-2.439,0.771-5.787,2.287-8.749,5.25 |
||||
c-5.592,5.592-6.47,11.67-6.47,11.67c0,1.938,1.575,3.492,3.523,3.492h48.51c1.946,0,3.521-1.558,3.521-3.492 |
||||
C56.055,62.768,54.211,55.906,49.529,51.225z"/> |
||||
|
||||
<radialGradient id="SVGID_4_" cx="17.0723" cy="18.4907" r="11.8931" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_4_)" stroke="#E55E03" d="M13.404,44.173c1.15-1.81,2.039-3.832,3.332-5.397 |
||||
c-0.514,1.027-1.669,4.084-1.669,5.148c0,5.186,10.366,9.079,14.688,10.438c-3.472,1.627-9.134-1.498-11.334-2.359 |
||||
c-3.601-1.419-4.071-3.063-5.89-4.854C12.523,47.135,12.878,45,13.404,44.173z"/> |
||||
|
||||
<radialGradient id="SVGID_5_" cx="31.8184" cy="19.3525" r="14.63" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_5_)" stroke="#E55E03" d="M45.777,43.924c-1.317-1.568-5.11-9.424-6.604-6.617 |
||||
c0.516,1.025,3.617,3.693,3.617,6.617c0,5.186-10.271,8.576-16.699,9.145c1.429,4.938,11.373,1.293,13.805-0.313 |
||||
c3.563-2.354,4.563-5.133,7.854-3.705C47.754,49.045,48.006,46.574,45.777,43.924z"/> |
||||
|
||||
<radialGradient id="SVGID_6_" cx="30.4893" cy="4.8721" r="5.2028" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_6_)" stroke="#E55E03" d="M30.777,54.167c0.357,0.836-0.153,1.983-0.352,2.813 |
||||
c-0.256,1.084-0.072,2.104,0.102,3.186c0.164,1.02,0.156,2.107,0.25,3.167c0.082,0.916,0.482,1.849,0.357,2.75"/> |
||||
|
||||
<radialGradient id="SVGID_7_" cx="23.2871" cy="5.3008" r="5.5143" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_7_)" stroke="#E55E03" d="M23.695,53.417c-0.508,0.584-0.476,2.209-0.398,3 |
||||
c0.116,1.183,0.456,2.099,0.333,3.333c-0.192,1.943,0.154,4.479-0.436,6.333"/> |
||||
|
||||
<radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FFD28F"/> |
||||
<stop offset="1" style="stop-color:#FFAB4F"/> |
||||
</radialGradient> |
||||
<path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357 |
||||
c0.086,10.2-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012 |
||||
C36.627,4.945,43.59,13.158,43.676,23.357z"/> |
||||
|
||||
<linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.501" y1="-12291.5195" x2="6492.1304" y2="-12384.9688" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3351.7349)"> |
||||
<stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/> |
||||
<stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/> |
||||
</linearGradient> |
||||
<path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386 |
||||
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247 |
||||
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/> |
||||
<path id="Hair_Young_Black_1_" fill="#5C5C5C" stroke="#353535" stroke-linecap="round" stroke-linejoin="round" d="M20.278,13.25 |
||||
c3.417,4.333,9.333,6.917,9.333,6.917l-1.417-3.5c0,0,7.094,4.691,8.083,4.333c0.968-0.2-1.082-3.807-1.082-3.807 |
||||
s3.138,1.795,4.854,3.969c1.803,2.28,4.285,3.504,4.285,3.504S47.027,2.719,27.289,2.744C8.278,2.709,12.058,27.678,12.058,27.678 |
||||
L14.695,17c0,0,0.914,5.757,1.399,4.875C17.861,15.211,18.861,11.5,20.278,13.25z"/> |
||||
</g> |
||||
</svg> |
||||
</y:Resource> |
||||
<y:Resource id="2"><?xml version="1.0" encoding="utf-8"?> |
||||
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" |
||||
width="57px" height="67px" viewBox="0 0 57 67" enable-background="new 0 0 57 67" xml:space="preserve"> |
||||
<g> |
||||
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"> |
||||
<stop offset="0.2711" style="stop-color:#FFAB4F"/> |
||||
<stop offset="1" style="stop-color:#FFD28F"/> |
||||
</linearGradient> |
||||
<path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109 |
||||
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77 |
||||
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/> |
||||
|
||||
<radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FFD28F"/> |
||||
<stop offset="1" style="stop-color:#FFAB4F"/> |
||||
</radialGradient> |
||||
<path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357 |
||||
c0.086,10.199-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012 |
||||
C36.627,4.945,43.59,13.158,43.676,23.357z"/> |
||||
|
||||
<linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.5" y1="-12286.8594" x2="6492.1294" y2="-12380.3086" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3350.4617)"> |
||||
<stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/> |
||||
<stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/> |
||||
</linearGradient> |
||||
<path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386 |
||||
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247 |
||||
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/> |
||||
<path id="Hair_Female_1_Red_1_" fill="#FAE1AA" stroke="#E2B354" stroke-linecap="round" stroke-linejoin="round" d="M28.372,0.5 |
||||
C17.537,0.5,8.269,7.748,9.153,26.125c0.563,6.563,5.862,12.042,9.366,13.531c-2.929-10.968-0.304-25.021-0.585-25.526 |
||||
c-0.281-0.505,3.536,6.728,3.536,6.728l3.183-8.312c5.541,4.28,0.393,11.309,1.049,11.058c4.26-1.631,5.34-9.228,5.34-9.228 |
||||
s2.729,3.657,2.701,5.504c-0.054,3.562,2.194-6.067,2.194-6.067l1.027,2.031c6.727,9.822,3.684,16.208,1.648,22.781 |
||||
c15.666-0.703,12.291-10.48,9.66-18.407C43.59,6.092,39.206,0.5,28.372,0.5z"/> |
||||
|
||||
<linearGradient id="body_1_" gradientUnits="userSpaceOnUse" x1="95.9063" y1="-3134.2153" x2="31.5133" y2="-3134.2153" gradientTransform="matrix(0.9852 0 0 -0.9852 -34.4844 -3031.9851)"> |
||||
<stop offset="0" style="stop-color:#49AD33"/> |
||||
<stop offset="1" style="stop-color:#C2DA92"/> |
||||
</linearGradient> |
||||
<path id="body_8_" fill="url(#body_1_)" stroke="#008D33" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51 |
||||
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-8.244-5.146-8.244-5.146 |
||||
c-1.444,6.983-8.555,8.786-13.007,8.786s-11.322-2.643-11.941-9.439c0,0-4.559,1.199-9.367,5.674 |
||||
C1.378,56.689,0.5,62.768,0.5,62.768z"/> |
||||
</g> |
||||
</svg> |
||||
</y:Resource> |
||||
</y:Resources> |
||||
</data> |
||||
</graphml> |
After Width: | Height: | Size: 19 KiB |
@ -0,0 +1,368 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd"> |
||||
<!--Created by yEd 3.12.2--> |
||||
<key for="graphml" id="d0" yfiles.type="resources"/> |
||||
<key for="port" id="d1" yfiles.type="portgraphics"/> |
||||
<key for="port" id="d2" yfiles.type="portgeometry"/> |
||||
<key for="port" id="d3" yfiles.type="portuserdata"/> |
||||
<key attr.name="url" attr.type="string" for="node" id="d4"/> |
||||
<key attr.name="description" attr.type="string" for="node" id="d5"/> |
||||
<key for="node" id="d6" yfiles.type="nodegraphics"/> |
||||
<key attr.name="Description" attr.type="string" for="graph" id="d7"/> |
||||
<key attr.name="url" attr.type="string" for="edge" id="d8"/> |
||||
<key attr.name="description" attr.type="string" for="edge" id="d9"/> |
||||
<key for="edge" id="d10" yfiles.type="edgegraphics"/> |
||||
<graph edgedefault="directed" id="G"> |
||||
<data key="d7"/> |
||||
<node id="n0"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="69.0" width="103.0" x="34.0" y="-11.5"/> |
||||
<y:Fill color="#ADF4A6" transparent="false"/> |
||||
<y:BorderStyle color="#FF0000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="36.68359375" x="33.158203125" y="25.1494140625">admin<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<node id="n1"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="69.0" width="103.0" x="193.0" y="-11.5"/> |
||||
<y:Fill color="#ADF4A6" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="38.025390625" x="32.4873046875" y="25.1494140625">author<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<node id="n2"> |
||||
<data key="d6"> |
||||
<y:SVGNode> |
||||
<y:Geometry height="64.53585815429688" width="56.560157775878906" x="216.21992111206055" y="-132.03585815429688"/> |
||||
<y:Fill color="#CCCCFF" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.905467987060547" y="-27.814727783203125">John, ID=2<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.113555908203125" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:SVGNodeProperties usingVisualBounds="true"/> |
||||
<y:SVGModel svgBoundsPolicy="0"> |
||||
<y:SVGContent refid="1"/> |
||||
</y:SVGModel> |
||||
</y:SVGNode> |
||||
</data> |
||||
</node> |
||||
<node id="n3"> |
||||
<data key="d6"> |
||||
<y:SVGNode> |
||||
<y:Geometry height="66.76200103759766" width="56.554100036621094" x="57.22294998168945" y="-133.14892959594727"/> |
||||
<y:Fill color="#CCCCFF" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.908496856689453" y="-27.701656341552734">Jane, ID=1<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.000484466552734" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:SVGNodeProperties usingVisualBounds="true"/> |
||||
<y:SVGModel svgBoundsPolicy="0"> |
||||
<y:SVGContent refid="2"/> |
||||
</y:SVGModel> |
||||
</y:SVGNode> |
||||
</data> |
||||
</node> |
||||
<node id="n4"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="69.0" width="103.0" x="34.0" y="197.5"/> |
||||
<y:Fill color="#99CCFF" transparent="false"/> |
||||
<y:BorderStyle color="#FF0000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.71484375" x="19.142578125" y="25.1494140625">updatePost<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<node id="n5"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="69.0" width="103.0" x="193.0" y="197.5"/> |
||||
<y:Fill color="#99CCFF" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="89.388671875" x="6.8056640625" y="25.1494140625">updateOwnPost<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<node id="n6"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="69.0" width="103.0" x="352.0" y="197.5"/> |
||||
<y:Fill color="#99CCFF" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="61.36328125" x="20.818359375" y="25.1494140625">createPost<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<node id="n7"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="29.535858154296875" width="103.0" x="193.0" y="167.96414184570312"/> |
||||
<y:Fill color="#FFCC00" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.03515625" x="19.482421875" y="5.4173431396484375">AuthorRule<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<edge id="e0" source="n4" target="n0"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#FF0000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e1" source="n4" target="n5"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#000000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e2" source="n1" target="n0"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#000000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e3" source="n6" target="n1"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"> |
||||
<y:Point x="403.5" y="23.0"/> |
||||
</y:Path> |
||||
<y:LineStyle color="#000000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e4" source="n1" target="n2"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#000000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e5" source="n0" target="n3"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#FF0000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e6" source="n7" target="n1"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#000000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
</graph> |
||||
<data key="d0"> |
||||
<y:Resources> |
||||
<y:Resource id="1"><?xml version="1.0" encoding="utf-8"?> |
||||
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" |
||||
width="57px" height="65px" viewBox="0 0 57 65" enable-background="new 0 0 57 65" xml:space="preserve"> |
||||
<g> |
||||
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"> |
||||
<stop offset="0.2711" style="stop-color:#FFAB4F"/> |
||||
<stop offset="1" style="stop-color:#FFD28F"/> |
||||
</linearGradient> |
||||
<path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109 |
||||
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77 |
||||
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/> |
||||
<path id="body_18_" fill="#ECECEC" stroke="#9B9B9B" stroke-miterlimit="10" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51 |
||||
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-11.244-6.146-11.244-6.146 |
||||
c-1.771,1.655-5.61,3.802-10.063,3.802c-4.453,0-8.292-2.146-10.063-3.802c0,0-5.755,0.586-11.189,6.021 |
||||
C1.378,56.689,0.5,62.768,0.5,62.768z"/> |
||||
|
||||
<radialGradient id="SVGID_2_" cx="22.6621" cy="21.707" r="17.7954" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_2_)" stroke="#E55E03" d="M28.106,33.486c-8.112,0-12.688,4.313-12.688,10.438 |
||||
c0,7.422,12.688,10.438,12.688,10.438s14.688-3.016,14.688-10.438C42.793,38.75,36.215,33.486,28.106,33.486z M26.288,53.051 |
||||
c0,0-7.135-2.093-8.805-7.201c-0.222-0.682,0.147-1.156,0.795-1.521V37.8h20.188v6.663c0.235,0.352,1.109,0.737,1.229,1.387 |
||||
C40.445,49.917,26.288,53.051,26.288,53.051z"/> |
||||
|
||||
<radialGradient id="SVGID_3_" cx="15.2056" cy="831.1875" r="32.3071" gradientTransform="matrix(1 0 0 1 0.0801 -773.6914)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_3_)" stroke="#E55E03" d="M49.529,51.225c-2.239-2.24-5.041-3.724-7.396-4.67 |
||||
c-2.854,5.51-14.021,7.807-14.021,7.807s-10.472-2.483-12.387-8.514c-2.439,0.771-5.787,2.287-8.749,5.25 |
||||
c-5.592,5.592-6.47,11.67-6.47,11.67c0,1.938,1.575,3.492,3.523,3.492h48.51c1.946,0,3.521-1.558,3.521-3.492 |
||||
C56.055,62.768,54.211,55.906,49.529,51.225z"/> |
||||
|
||||
<radialGradient id="SVGID_4_" cx="17.0723" cy="18.4907" r="11.8931" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_4_)" stroke="#E55E03" d="M13.404,44.173c1.15-1.81,2.039-3.832,3.332-5.397 |
||||
c-0.514,1.027-1.669,4.084-1.669,5.148c0,5.186,10.366,9.079,14.688,10.438c-3.472,1.627-9.134-1.498-11.334-2.359 |
||||
c-3.601-1.419-4.071-3.063-5.89-4.854C12.523,47.135,12.878,45,13.404,44.173z"/> |
||||
|
||||
<radialGradient id="SVGID_5_" cx="31.8184" cy="19.3525" r="14.63" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_5_)" stroke="#E55E03" d="M45.777,43.924c-1.317-1.568-5.11-9.424-6.604-6.617 |
||||
c0.516,1.025,3.617,3.693,3.617,6.617c0,5.186-10.271,8.576-16.699,9.145c1.429,4.938,11.373,1.293,13.805-0.313 |
||||
c3.563-2.354,4.563-5.133,7.854-3.705C47.754,49.045,48.006,46.574,45.777,43.924z"/> |
||||
|
||||
<radialGradient id="SVGID_6_" cx="30.4893" cy="4.8721" r="5.2028" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_6_)" stroke="#E55E03" d="M30.777,54.167c0.357,0.836-0.153,1.983-0.352,2.813 |
||||
c-0.256,1.084-0.072,2.104,0.102,3.186c0.164,1.02,0.156,2.107,0.25,3.167c0.082,0.916,0.482,1.849,0.357,2.75"/> |
||||
|
||||
<radialGradient id="SVGID_7_" cx="23.2871" cy="5.3008" r="5.5143" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_7_)" stroke="#E55E03" d="M23.695,53.417c-0.508,0.584-0.476,2.209-0.398,3 |
||||
c0.116,1.183,0.456,2.099,0.333,3.333c-0.192,1.943,0.154,4.479-0.436,6.333"/> |
||||
|
||||
<radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FFD28F"/> |
||||
<stop offset="1" style="stop-color:#FFAB4F"/> |
||||
</radialGradient> |
||||
<path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357 |
||||
c0.086,10.2-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012 |
||||
C36.627,4.945,43.59,13.158,43.676,23.357z"/> |
||||
|
||||
<linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.501" y1="-12291.5195" x2="6492.1304" y2="-12384.9688" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3351.7349)"> |
||||
<stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/> |
||||
<stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/> |
||||
</linearGradient> |
||||
<path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386 |
||||
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247 |
||||
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/> |
||||
<path id="Hair_Young_Black_1_" fill="#5C5C5C" stroke="#353535" stroke-linecap="round" stroke-linejoin="round" d="M20.278,13.25 |
||||
c3.417,4.333,9.333,6.917,9.333,6.917l-1.417-3.5c0,0,7.094,4.691,8.083,4.333c0.968-0.2-1.082-3.807-1.082-3.807 |
||||
s3.138,1.795,4.854,3.969c1.803,2.28,4.285,3.504,4.285,3.504S47.027,2.719,27.289,2.744C8.278,2.709,12.058,27.678,12.058,27.678 |
||||
L14.695,17c0,0,0.914,5.757,1.399,4.875C17.861,15.211,18.861,11.5,20.278,13.25z"/> |
||||
</g> |
||||
</svg> |
||||
</y:Resource> |
||||
<y:Resource id="2"><?xml version="1.0" encoding="utf-8"?> |
||||
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" |
||||
width="57px" height="67px" viewBox="0 0 57 67" enable-background="new 0 0 57 67" xml:space="preserve"> |
||||
<g> |
||||
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"> |
||||
<stop offset="0.2711" style="stop-color:#FFAB4F"/> |
||||
<stop offset="1" style="stop-color:#FFD28F"/> |
||||
</linearGradient> |
||||
<path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109 |
||||
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77 |
||||
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/> |
||||
|
||||
<radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FFD28F"/> |
||||
<stop offset="1" style="stop-color:#FFAB4F"/> |
||||
</radialGradient> |
||||
<path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357 |
||||
c0.086,10.199-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012 |
||||
C36.627,4.945,43.59,13.158,43.676,23.357z"/> |
||||
|
||||
<linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.5" y1="-12286.8594" x2="6492.1294" y2="-12380.3086" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3350.4617)"> |
||||
<stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/> |
||||
<stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/> |
||||
</linearGradient> |
||||
<path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386 |
||||
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247 |
||||
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/> |
||||
<path id="Hair_Female_1_Red_1_" fill="#FAE1AA" stroke="#E2B354" stroke-linecap="round" stroke-linejoin="round" d="M28.372,0.5 |
||||
C17.537,0.5,8.269,7.748,9.153,26.125c0.563,6.563,5.862,12.042,9.366,13.531c-2.929-10.968-0.304-25.021-0.585-25.526 |
||||
c-0.281-0.505,3.536,6.728,3.536,6.728l3.183-8.312c5.541,4.28,0.393,11.309,1.049,11.058c4.26-1.631,5.34-9.228,5.34-9.228 |
||||
s2.729,3.657,2.701,5.504c-0.054,3.562,2.194-6.067,2.194-6.067l1.027,2.031c6.727,9.822,3.684,16.208,1.648,22.781 |
||||
c15.666-0.703,12.291-10.48,9.66-18.407C43.59,6.092,39.206,0.5,28.372,0.5z"/> |
||||
|
||||
<linearGradient id="body_1_" gradientUnits="userSpaceOnUse" x1="95.9063" y1="-3134.2153" x2="31.5133" y2="-3134.2153" gradientTransform="matrix(0.9852 0 0 -0.9852 -34.4844 -3031.9851)"> |
||||
<stop offset="0" style="stop-color:#49AD33"/> |
||||
<stop offset="1" style="stop-color:#C2DA92"/> |
||||
</linearGradient> |
||||
<path id="body_8_" fill="url(#body_1_)" stroke="#008D33" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51 |
||||
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-8.244-5.146-8.244-5.146 |
||||
c-1.444,6.983-8.555,8.786-13.007,8.786s-11.322-2.643-11.941-9.439c0,0-4.559,1.199-9.367,5.674 |
||||
C1.378,56.689,0.5,62.768,0.5,62.768z"/> |
||||
</g> |
||||
</svg> |
||||
</y:Resource> |
||||
</y:Resources> |
||||
</data> |
||||
</graphml> |
After Width: | Height: | Size: 19 KiB |
@ -0,0 +1,312 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd"> |
||||
<!--Created by yEd 3.12.2--> |
||||
<key for="graphml" id="d0" yfiles.type="resources"/> |
||||
<key for="port" id="d1" yfiles.type="portgraphics"/> |
||||
<key for="port" id="d2" yfiles.type="portgeometry"/> |
||||
<key for="port" id="d3" yfiles.type="portuserdata"/> |
||||
<key attr.name="url" attr.type="string" for="node" id="d4"/> |
||||
<key attr.name="description" attr.type="string" for="node" id="d5"/> |
||||
<key for="node" id="d6" yfiles.type="nodegraphics"/> |
||||
<key attr.name="Description" attr.type="string" for="graph" id="d7"/> |
||||
<key attr.name="url" attr.type="string" for="edge" id="d8"/> |
||||
<key attr.name="description" attr.type="string" for="edge" id="d9"/> |
||||
<key for="edge" id="d10" yfiles.type="edgegraphics"/> |
||||
<graph edgedefault="directed" id="G"> |
||||
<data key="d7"/> |
||||
<node id="n0"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="69.0" width="103.0" x="34.0" y="-11.5"/> |
||||
<y:Fill color="#ADF4A6" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="36.68359375" x="33.158203125" y="25.1494140625">admin<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<node id="n1"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="69.0" width="103.0" x="193.0" y="-11.5"/> |
||||
<y:Fill color="#ADF4A6" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="38.025390625" x="32.4873046875" y="25.1494140625">author<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<node id="n2"> |
||||
<data key="d6"> |
||||
<y:SVGNode> |
||||
<y:Geometry height="64.53585815429688" width="56.560157775878906" x="216.21992111206055" y="-132.03585815429688"/> |
||||
<y:Fill color="#CCCCFF" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.905467987060547" y="-27.814727783203125">John, ID=2<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.113555908203125" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:SVGNodeProperties usingVisualBounds="true"/> |
||||
<y:SVGModel svgBoundsPolicy="0"> |
||||
<y:SVGContent refid="1"/> |
||||
</y:SVGModel> |
||||
</y:SVGNode> |
||||
</data> |
||||
</node> |
||||
<node id="n3"> |
||||
<data key="d6"> |
||||
<y:SVGNode> |
||||
<y:Geometry height="66.76200103759766" width="56.554100036621094" x="57.22294998168945" y="-133.14892959594727"/> |
||||
<y:Fill color="#CCCCFF" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.908496856689453" y="-27.701656341552734">Jane, ID=1<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.000484466552734" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:SVGNodeProperties usingVisualBounds="true"/> |
||||
<y:SVGModel svgBoundsPolicy="0"> |
||||
<y:SVGContent refid="2"/> |
||||
</y:SVGModel> |
||||
</y:SVGNode> |
||||
</data> |
||||
</node> |
||||
<node id="n4"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="69.0" width="103.0" x="34.0" y="197.5"/> |
||||
<y:Fill color="#99CCFF" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.71484375" x="19.142578125" y="25.1494140625">updatePost<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<node id="n5"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="69.0" width="103.0" x="193.0" y="197.5"/> |
||||
<y:Fill color="#99CCFF" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="61.36328125" x="20.818359375" y="25.1494140625">createPost<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<edge id="e0" source="n4" target="n0"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#000000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e1" source="n1" target="n0"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#000000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e2" source="n1" target="n2"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#000000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e3" source="n0" target="n3"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#000000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e4" source="n5" target="n1"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#000000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
</graph> |
||||
<data key="d0"> |
||||
<y:Resources> |
||||
<y:Resource id="1"><?xml version="1.0" encoding="utf-8"?> |
||||
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" |
||||
width="57px" height="65px" viewBox="0 0 57 65" enable-background="new 0 0 57 65" xml:space="preserve"> |
||||
<g> |
||||
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"> |
||||
<stop offset="0.2711" style="stop-color:#FFAB4F"/> |
||||
<stop offset="1" style="stop-color:#FFD28F"/> |
||||
</linearGradient> |
||||
<path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109 |
||||
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77 |
||||
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/> |
||||
<path id="body_18_" fill="#ECECEC" stroke="#9B9B9B" stroke-miterlimit="10" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51 |
||||
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-11.244-6.146-11.244-6.146 |
||||
c-1.771,1.655-5.61,3.802-10.063,3.802c-4.453,0-8.292-2.146-10.063-3.802c0,0-5.755,0.586-11.189,6.021 |
||||
C1.378,56.689,0.5,62.768,0.5,62.768z"/> |
||||
|
||||
<radialGradient id="SVGID_2_" cx="22.6621" cy="21.707" r="17.7954" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_2_)" stroke="#E55E03" d="M28.106,33.486c-8.112,0-12.688,4.313-12.688,10.438 |
||||
c0,7.422,12.688,10.438,12.688,10.438s14.688-3.016,14.688-10.438C42.793,38.75,36.215,33.486,28.106,33.486z M26.288,53.051 |
||||
c0,0-7.135-2.093-8.805-7.201c-0.222-0.682,0.147-1.156,0.795-1.521V37.8h20.188v6.663c0.235,0.352,1.109,0.737,1.229,1.387 |
||||
C40.445,49.917,26.288,53.051,26.288,53.051z"/> |
||||
|
||||
<radialGradient id="SVGID_3_" cx="15.2056" cy="831.1875" r="32.3071" gradientTransform="matrix(1 0 0 1 0.0801 -773.6914)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_3_)" stroke="#E55E03" d="M49.529,51.225c-2.239-2.24-5.041-3.724-7.396-4.67 |
||||
c-2.854,5.51-14.021,7.807-14.021,7.807s-10.472-2.483-12.387-8.514c-2.439,0.771-5.787,2.287-8.749,5.25 |
||||
c-5.592,5.592-6.47,11.67-6.47,11.67c0,1.938,1.575,3.492,3.523,3.492h48.51c1.946,0,3.521-1.558,3.521-3.492 |
||||
C56.055,62.768,54.211,55.906,49.529,51.225z"/> |
||||
|
||||
<radialGradient id="SVGID_4_" cx="17.0723" cy="18.4907" r="11.8931" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_4_)" stroke="#E55E03" d="M13.404,44.173c1.15-1.81,2.039-3.832,3.332-5.397 |
||||
c-0.514,1.027-1.669,4.084-1.669,5.148c0,5.186,10.366,9.079,14.688,10.438c-3.472,1.627-9.134-1.498-11.334-2.359 |
||||
c-3.601-1.419-4.071-3.063-5.89-4.854C12.523,47.135,12.878,45,13.404,44.173z"/> |
||||
|
||||
<radialGradient id="SVGID_5_" cx="31.8184" cy="19.3525" r="14.63" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_5_)" stroke="#E55E03" d="M45.777,43.924c-1.317-1.568-5.11-9.424-6.604-6.617 |
||||
c0.516,1.025,3.617,3.693,3.617,6.617c0,5.186-10.271,8.576-16.699,9.145c1.429,4.938,11.373,1.293,13.805-0.313 |
||||
c3.563-2.354,4.563-5.133,7.854-3.705C47.754,49.045,48.006,46.574,45.777,43.924z"/> |
||||
|
||||
<radialGradient id="SVGID_6_" cx="30.4893" cy="4.8721" r="5.2028" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_6_)" stroke="#E55E03" d="M30.777,54.167c0.357,0.836-0.153,1.983-0.352,2.813 |
||||
c-0.256,1.084-0.072,2.104,0.102,3.186c0.164,1.02,0.156,2.107,0.25,3.167c0.082,0.916,0.482,1.849,0.357,2.75"/> |
||||
|
||||
<radialGradient id="SVGID_7_" cx="23.2871" cy="5.3008" r="5.5143" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_7_)" stroke="#E55E03" d="M23.695,53.417c-0.508,0.584-0.476,2.209-0.398,3 |
||||
c0.116,1.183,0.456,2.099,0.333,3.333c-0.192,1.943,0.154,4.479-0.436,6.333"/> |
||||
|
||||
<radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FFD28F"/> |
||||
<stop offset="1" style="stop-color:#FFAB4F"/> |
||||
</radialGradient> |
||||
<path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357 |
||||
c0.086,10.2-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012 |
||||
C36.627,4.945,43.59,13.158,43.676,23.357z"/> |
||||
|
||||
<linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.501" y1="-12291.5195" x2="6492.1304" y2="-12384.9688" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3351.7349)"> |
||||
<stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/> |
||||
<stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/> |
||||
</linearGradient> |
||||
<path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386 |
||||
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247 |
||||
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/> |
||||
<path id="Hair_Young_Black_1_" fill="#5C5C5C" stroke="#353535" stroke-linecap="round" stroke-linejoin="round" d="M20.278,13.25 |
||||
c3.417,4.333,9.333,6.917,9.333,6.917l-1.417-3.5c0,0,7.094,4.691,8.083,4.333c0.968-0.2-1.082-3.807-1.082-3.807 |
||||
s3.138,1.795,4.854,3.969c1.803,2.28,4.285,3.504,4.285,3.504S47.027,2.719,27.289,2.744C8.278,2.709,12.058,27.678,12.058,27.678 |
||||
L14.695,17c0,0,0.914,5.757,1.399,4.875C17.861,15.211,18.861,11.5,20.278,13.25z"/> |
||||
</g> |
||||
</svg> |
||||
</y:Resource> |
||||
<y:Resource id="2"><?xml version="1.0" encoding="utf-8"?> |
||||
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" |
||||
width="57px" height="67px" viewBox="0 0 57 67" enable-background="new 0 0 57 67" xml:space="preserve"> |
||||
<g> |
||||
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"> |
||||
<stop offset="0.2711" style="stop-color:#FFAB4F"/> |
||||
<stop offset="1" style="stop-color:#FFD28F"/> |
||||
</linearGradient> |
||||
<path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109 |
||||
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77 |
||||
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/> |
||||
|
||||
<radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FFD28F"/> |
||||
<stop offset="1" style="stop-color:#FFAB4F"/> |
||||
</radialGradient> |
||||
<path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357 |
||||
c0.086,10.199-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012 |
||||
C36.627,4.945,43.59,13.158,43.676,23.357z"/> |
||||
|
||||
<linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.5" y1="-12286.8594" x2="6492.1294" y2="-12380.3086" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3350.4617)"> |
||||
<stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/> |
||||
<stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/> |
||||
</linearGradient> |
||||
<path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386 |
||||
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247 |
||||
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/> |
||||
<path id="Hair_Female_1_Red_1_" fill="#FAE1AA" stroke="#E2B354" stroke-linecap="round" stroke-linejoin="round" d="M28.372,0.5 |
||||
C17.537,0.5,8.269,7.748,9.153,26.125c0.563,6.563,5.862,12.042,9.366,13.531c-2.929-10.968-0.304-25.021-0.585-25.526 |
||||
c-0.281-0.505,3.536,6.728,3.536,6.728l3.183-8.312c5.541,4.28,0.393,11.309,1.049,11.058c4.26-1.631,5.34-9.228,5.34-9.228 |
||||
s2.729,3.657,2.701,5.504c-0.054,3.562,2.194-6.067,2.194-6.067l1.027,2.031c6.727,9.822,3.684,16.208,1.648,22.781 |
||||
c15.666-0.703,12.291-10.48,9.66-18.407C43.59,6.092,39.206,0.5,28.372,0.5z"/> |
||||
|
||||
<linearGradient id="body_1_" gradientUnits="userSpaceOnUse" x1="95.9063" y1="-3134.2153" x2="31.5133" y2="-3134.2153" gradientTransform="matrix(0.9852 0 0 -0.9852 -34.4844 -3031.9851)"> |
||||
<stop offset="0" style="stop-color:#49AD33"/> |
||||
<stop offset="1" style="stop-color:#C2DA92"/> |
||||
</linearGradient> |
||||
<path id="body_8_" fill="url(#body_1_)" stroke="#008D33" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51 |
||||
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-8.244-5.146-8.244-5.146 |
||||
c-1.444,6.983-8.555,8.786-13.007,8.786s-11.322-2.643-11.941-9.439c0,0-4.559,1.199-9.367,5.674 |
||||
C1.378,56.689,0.5,62.768,0.5,62.768z"/> |
||||
</g> |
||||
</svg> |
||||
</y:Resource> |
||||
</y:Resources> |
||||
</data> |
||||
</graphml> |
After Width: | Height: | Size: 16 KiB |
@ -0,0 +1,368 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd"> |
||||
<!--Created by yEd 3.12.2--> |
||||
<key for="graphml" id="d0" yfiles.type="resources"/> |
||||
<key for="port" id="d1" yfiles.type="portgraphics"/> |
||||
<key for="port" id="d2" yfiles.type="portgeometry"/> |
||||
<key for="port" id="d3" yfiles.type="portuserdata"/> |
||||
<key attr.name="url" attr.type="string" for="node" id="d4"/> |
||||
<key attr.name="description" attr.type="string" for="node" id="d5"/> |
||||
<key for="node" id="d6" yfiles.type="nodegraphics"/> |
||||
<key attr.name="Description" attr.type="string" for="graph" id="d7"/> |
||||
<key attr.name="url" attr.type="string" for="edge" id="d8"/> |
||||
<key attr.name="description" attr.type="string" for="edge" id="d9"/> |
||||
<key for="edge" id="d10" yfiles.type="edgegraphics"/> |
||||
<graph edgedefault="directed" id="G"> |
||||
<data key="d7"/> |
||||
<node id="n0"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="69.0" width="103.0" x="34.0" y="-11.5"/> |
||||
<y:Fill color="#ADF4A6" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="36.68359375" x="33.158203125" y="25.1494140625">admin<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<node id="n1"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="69.0" width="103.0" x="193.0" y="-11.5"/> |
||||
<y:Fill color="#ADF4A6" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="38.025390625" x="32.4873046875" y="25.1494140625">author<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<node id="n2"> |
||||
<data key="d6"> |
||||
<y:SVGNode> |
||||
<y:Geometry height="64.53585815429688" width="56.560157775878906" x="216.21992111206055" y="-132.03585815429688"/> |
||||
<y:Fill color="#CCCCFF" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.905467987060547" y="-27.814727783203125">John, ID=2<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.113555908203125" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:SVGNodeProperties usingVisualBounds="true"/> |
||||
<y:SVGModel svgBoundsPolicy="0"> |
||||
<y:SVGContent refid="1"/> |
||||
</y:SVGModel> |
||||
</y:SVGNode> |
||||
</data> |
||||
</node> |
||||
<node id="n3"> |
||||
<data key="d6"> |
||||
<y:SVGNode> |
||||
<y:Geometry height="66.76200103759766" width="56.554100036621094" x="57.22294998168945" y="-133.14892959594727"/> |
||||
<y:Fill color="#CCCCFF" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="62.37109375" x="-2.908496856689453" y="-27.701656341552734">Jane, ID=1<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-9.000484466552734" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:SVGNodeProperties usingVisualBounds="true"/> |
||||
<y:SVGModel svgBoundsPolicy="0"> |
||||
<y:SVGContent refid="2"/> |
||||
</y:SVGModel> |
||||
</y:SVGNode> |
||||
</data> |
||||
</node> |
||||
<node id="n4"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="69.0" width="103.0" x="34.0" y="197.5"/> |
||||
<y:Fill color="#99CCFF" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.71484375" x="19.142578125" y="25.1494140625">updatePost<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<node id="n5"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="69.0" width="103.0" x="193.0" y="197.5"/> |
||||
<y:Fill color="#99CCFF" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="89.388671875" x="6.8056640625" y="25.1494140625">updateOwnPost<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<node id="n6"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="69.0" width="103.0" x="352.0" y="197.5"/> |
||||
<y:Fill color="#99CCFF" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="61.36328125" x="20.818359375" y="25.1494140625">createPost<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<node id="n7"> |
||||
<data key="d6"> |
||||
<y:ShapeNode> |
||||
<y:Geometry height="29.535858154296875" width="103.0" x="193.0" y="167.96414184570312"/> |
||||
<y:Fill color="#FFCC00" transparent="false"/> |
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/> |
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="64.03515625" x="19.482421875" y="5.4173431396484375">AuthorRule<y:LabelModel> |
||||
<y:SmartNodeLabelModel distance="4.0"/> |
||||
</y:LabelModel> |
||||
<y:ModelParameter> |
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/> |
||||
</y:ModelParameter> |
||||
</y:NodeLabel> |
||||
<y:Shape type="roundrectangle"/> |
||||
</y:ShapeNode> |
||||
</data> |
||||
</node> |
||||
<edge id="e0" source="n4" target="n0"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#000000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e1" source="n4" target="n5"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#000000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e2" source="n1" target="n0"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#000000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e3" source="n6" target="n1"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"> |
||||
<y:Point x="403.5" y="23.0"/> |
||||
</y:Path> |
||||
<y:LineStyle color="#000000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e4" source="n1" target="n2"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#000000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e5" source="n0" target="n3"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#000000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
<edge id="e6" source="n7" target="n1"> |
||||
<data key="d10"> |
||||
<y:PolyLineEdge> |
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/> |
||||
<y:LineStyle color="#000000" type="line" width="1.0"/> |
||||
<y:Arrows source="none" target="standard"/> |
||||
<y:BendStyle smoothed="false"/> |
||||
</y:PolyLineEdge> |
||||
</data> |
||||
</edge> |
||||
</graph> |
||||
<data key="d0"> |
||||
<y:Resources> |
||||
<y:Resource id="1"><?xml version="1.0" encoding="utf-8"?> |
||||
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" |
||||
width="57px" height="65px" viewBox="0 0 57 65" enable-background="new 0 0 57 65" xml:space="preserve"> |
||||
<g> |
||||
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"> |
||||
<stop offset="0.2711" style="stop-color:#FFAB4F"/> |
||||
<stop offset="1" style="stop-color:#FFD28F"/> |
||||
</linearGradient> |
||||
<path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109 |
||||
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77 |
||||
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/> |
||||
<path id="body_18_" fill="#ECECEC" stroke="#9B9B9B" stroke-miterlimit="10" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51 |
||||
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-11.244-6.146-11.244-6.146 |
||||
c-1.771,1.655-5.61,3.802-10.063,3.802c-4.453,0-8.292-2.146-10.063-3.802c0,0-5.755,0.586-11.189,6.021 |
||||
C1.378,56.689,0.5,62.768,0.5,62.768z"/> |
||||
|
||||
<radialGradient id="SVGID_2_" cx="22.6621" cy="21.707" r="17.7954" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_2_)" stroke="#E55E03" d="M28.106,33.486c-8.112,0-12.688,4.313-12.688,10.438 |
||||
c0,7.422,12.688,10.438,12.688,10.438s14.688-3.016,14.688-10.438C42.793,38.75,36.215,33.486,28.106,33.486z M26.288,53.051 |
||||
c0,0-7.135-2.093-8.805-7.201c-0.222-0.682,0.147-1.156,0.795-1.521V37.8h20.188v6.663c0.235,0.352,1.109,0.737,1.229,1.387 |
||||
C40.445,49.917,26.288,53.051,26.288,53.051z"/> |
||||
|
||||
<radialGradient id="SVGID_3_" cx="15.2056" cy="831.1875" r="32.3071" gradientTransform="matrix(1 0 0 1 0.0801 -773.6914)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_3_)" stroke="#E55E03" d="M49.529,51.225c-2.239-2.24-5.041-3.724-7.396-4.67 |
||||
c-2.854,5.51-14.021,7.807-14.021,7.807s-10.472-2.483-12.387-8.514c-2.439,0.771-5.787,2.287-8.749,5.25 |
||||
c-5.592,5.592-6.47,11.67-6.47,11.67c0,1.938,1.575,3.492,3.523,3.492h48.51c1.946,0,3.521-1.558,3.521-3.492 |
||||
C56.055,62.768,54.211,55.906,49.529,51.225z"/> |
||||
|
||||
<radialGradient id="SVGID_4_" cx="17.0723" cy="18.4907" r="11.8931" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_4_)" stroke="#E55E03" d="M13.404,44.173c1.15-1.81,2.039-3.832,3.332-5.397 |
||||
c-0.514,1.027-1.669,4.084-1.669,5.148c0,5.186,10.366,9.079,14.688,10.438c-3.472,1.627-9.134-1.498-11.334-2.359 |
||||
c-3.601-1.419-4.071-3.063-5.89-4.854C12.523,47.135,12.878,45,13.404,44.173z"/> |
||||
|
||||
<radialGradient id="SVGID_5_" cx="31.8184" cy="19.3525" r="14.63" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_5_)" stroke="#E55E03" d="M45.777,43.924c-1.317-1.568-5.11-9.424-6.604-6.617 |
||||
c0.516,1.025,3.617,3.693,3.617,6.617c0,5.186-10.271,8.576-16.699,9.145c1.429,4.938,11.373,1.293,13.805-0.313 |
||||
c3.563-2.354,4.563-5.133,7.854-3.705C47.754,49.045,48.006,46.574,45.777,43.924z"/> |
||||
|
||||
<radialGradient id="SVGID_6_" cx="30.4893" cy="4.8721" r="5.2028" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_6_)" stroke="#E55E03" d="M30.777,54.167c0.357,0.836-0.153,1.983-0.352,2.813 |
||||
c-0.256,1.084-0.072,2.104,0.102,3.186c0.164,1.02,0.156,2.107,0.25,3.167c0.082,0.916,0.482,1.849,0.357,2.75"/> |
||||
|
||||
<radialGradient id="SVGID_7_" cx="23.2871" cy="5.3008" r="5.5143" gradientTransform="matrix(1 0 0 -1 0.04 64.1543)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FCB57A"/> |
||||
<stop offset="1" style="stop-color:#FF8C36"/> |
||||
</radialGradient> |
||||
<path fill="url(#SVGID_7_)" stroke="#E55E03" d="M23.695,53.417c-0.508,0.584-0.476,2.209-0.398,3 |
||||
c0.116,1.183,0.456,2.099,0.333,3.333c-0.192,1.943,0.154,4.479-0.436,6.333"/> |
||||
|
||||
<radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FFD28F"/> |
||||
<stop offset="1" style="stop-color:#FFAB4F"/> |
||||
</radialGradient> |
||||
<path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357 |
||||
c0.086,10.2-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012 |
||||
C36.627,4.945,43.59,13.158,43.676,23.357z"/> |
||||
|
||||
<linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.501" y1="-12291.5195" x2="6492.1304" y2="-12384.9688" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3351.7349)"> |
||||
<stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/> |
||||
<stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/> |
||||
</linearGradient> |
||||
<path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386 |
||||
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247 |
||||
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/> |
||||
<path id="Hair_Young_Black_1_" fill="#5C5C5C" stroke="#353535" stroke-linecap="round" stroke-linejoin="round" d="M20.278,13.25 |
||||
c3.417,4.333,9.333,6.917,9.333,6.917l-1.417-3.5c0,0,7.094,4.691,8.083,4.333c0.968-0.2-1.082-3.807-1.082-3.807 |
||||
s3.138,1.795,4.854,3.969c1.803,2.28,4.285,3.504,4.285,3.504S47.027,2.719,27.289,2.744C8.278,2.709,12.058,27.678,12.058,27.678 |
||||
L14.695,17c0,0,0.914,5.757,1.399,4.875C17.861,15.211,18.861,11.5,20.278,13.25z"/> |
||||
</g> |
||||
</svg> |
||||
</y:Resource> |
||||
<y:Resource id="2"><?xml version="1.0" encoding="utf-8"?> |
||||
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" |
||||
width="57px" height="67px" viewBox="0 0 57 67" enable-background="new 0 0 57 67" xml:space="preserve"> |
||||
<g> |
||||
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3398" y1="3115.7266" x2="27.5807" y2="3145.5239" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)"> |
||||
<stop offset="0.2711" style="stop-color:#FFAB4F"/> |
||||
<stop offset="1" style="stop-color:#FFD28F"/> |
||||
</linearGradient> |
||||
<path fill="url(#SVGID_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M49.529,51.225c-4.396-4.396-10.951-5.884-12.063-6.109 |
||||
V37.8H19.278c0,0,0.038,6.903,0,6.868c0,0-6.874,0.997-12.308,6.432C1.378,56.691,0.5,62.77,0.5,62.77 |
||||
c0,1.938,1.575,3.492,3.523,3.492h48.51c1.947,0,3.521-1.558,3.521-3.492C56.055,62.768,54.211,55.906,49.529,51.225z"/> |
||||
|
||||
<radialGradient id="face_x5F_white_1_" cx="27.5835" cy="3117.4922" r="23.425" fx="23.0139" fy="3115.0024" gradientTransform="matrix(1 0 0 1 0.3203 -3091.7656)" gradientUnits="userSpaceOnUse"> |
||||
<stop offset="0" style="stop-color:#FFD28F"/> |
||||
<stop offset="1" style="stop-color:#FFAB4F"/> |
||||
</radialGradient> |
||||
<path id="face_x5F_white_3_" fill="url(#face_x5F_white_1_)" stroke="#ED9135" stroke-miterlimit="10" d="M43.676,23.357 |
||||
c0.086,10.199-6.738,18.52-15.25,18.586c-8.5,0.068-15.464-8.146-15.55-18.344C12.794,13.4,19.618,5.079,28.123,5.012 |
||||
C36.627,4.945,43.59,13.158,43.676,23.357z"/> |
||||
|
||||
<linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="6468.5" y1="-12286.8594" x2="6492.1294" y2="-12380.3086" gradientTransform="matrix(0.275 0 0 -0.2733 -1752.8849 -3350.4617)"> |
||||
<stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/> |
||||
<stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/> |
||||
</linearGradient> |
||||
<path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M28.415,5.625c-6.035,0.047-10.747,4.493-12.787,10.386 |
||||
c-0.664,1.919-0.294,4.043,0.98,5.629c2.73,3.398,5.729,6.283,9.461,8.088c3.137,1.518,7.535,2.385,11.893,1.247 |
||||
c2.274-0.592,3.988-2.459,4.375-4.766c0.187-1.094,0.293-2.289,0.283-3.553C42.54,13.244,36.729,5.56,28.415,5.625z"/> |
||||
<path id="Hair_Female_1_Red_1_" fill="#FAE1AA" stroke="#E2B354" stroke-linecap="round" stroke-linejoin="round" d="M28.372,0.5 |
||||
C17.537,0.5,8.269,7.748,9.153,26.125c0.563,6.563,5.862,12.042,9.366,13.531c-2.929-10.968-0.304-25.021-0.585-25.526 |
||||
c-0.281-0.505,3.536,6.728,3.536,6.728l3.183-8.312c5.541,4.28,0.393,11.309,1.049,11.058c4.26-1.631,5.34-9.228,5.34-9.228 |
||||
s2.729,3.657,2.701,5.504c-0.054,3.562,2.194-6.067,2.194-6.067l1.027,2.031c6.727,9.822,3.684,16.208,1.648,22.781 |
||||
c15.666-0.703,12.291-10.48,9.66-18.407C43.59,6.092,39.206,0.5,28.372,0.5z"/> |
||||
|
||||
<linearGradient id="body_1_" gradientUnits="userSpaceOnUse" x1="95.9063" y1="-3134.2153" x2="31.5133" y2="-3134.2153" gradientTransform="matrix(0.9852 0 0 -0.9852 -34.4844 -3031.9851)"> |
||||
<stop offset="0" style="stop-color:#49AD33"/> |
||||
<stop offset="1" style="stop-color:#C2DA92"/> |
||||
</linearGradient> |
||||
<path id="body_8_" fill="url(#body_1_)" stroke="#008D33" d="M0.5,62.768c0,1.938,1.575,3.494,3.523,3.494h48.51 |
||||
c1.947,0,3.521-1.559,3.521-3.494c0,0-1.844-6.861-6.525-11.543c-4.815-4.813-8.244-5.146-8.244-5.146 |
||||
c-1.444,6.983-8.555,8.786-13.007,8.786s-11.322-2.643-11.941-9.439c0,0-4.559,1.199-9.367,5.674 |
||||
C1.378,56.689,0.5,62.768,0.5,62.768z"/> |
||||
</g> |
||||
</svg> |
||||
</y:Resource> |
||||
</y:Resources> |
||||
</data> |
||||
</graphml> |
After Width: | Height: | Size: 18 KiB |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue