Commit b0a6931a by Qiang Xue

Merge branch 'master' of git://github.com/yiisoft/yii2

Conflicts: docs/guide-uk/concept-autoloading.md
parents 55e761a6 1f39a380
......@@ -53,8 +53,8 @@ Gestión de las peticiones
* [Peticiones (Requests)](runtime-requests.md)
* [Respuestas (Responses)](runtime-responses.md)
* [Sesiones (Sessions) y Cookies](runtime-sessions-cookies.md)
* **TBD** [Gestión de errores](runtime-handling-errors.md)
* **TBD** [Registro de anotaciones](runtime-logging.md)
* [Gestión de errores](runtime-handling-errors.md)
* [Registro de anotaciones](runtime-logging.md)
Conceptos clave
......
Registro de anotaciones
=======================
Yii proporciona un poderoso framework dedicado al registro de anotaciones (logging) que es altamente personalizable y
extensible. Usando este framework se pueden guardar fácilmente anotaciones (logs) de varios tipos de mensajes,
filtrarlos, y unificarlos en diferentes destinos que pueden ser archivos, bases de datos o emails.
Usar el framework de registro de anotaciones de Yii involucra los siguientes pasos:
* Registrar [mensajes de las anotaciones](#log-messages) en distintos lugares del código;
* Configurar los [destinos de las anotaciones](#log-targets) en la configuración de la aplicación para filtrar y
exportar los mensajes de las anotaciones;
* Examinar los mensajes filtrados de los las anotaciones exportadas para diferentes destinos
(p. ej. [Yii debugger](tool-debugger.md)).
En esta sección, se describirán principalmente los dos primeros pasos.
## Anotación de Messages <a name="log-messages"></a>
Registrar mensajes de anotación es tan simple como llamar a uno de los siguientes métodos de registro de anotaciones.
* [[Yii::trace()]]: registra un mensaje para trazar el funcionamiento de una sección de código. Se usa principalmente
para tareas de desarrollo.
* [[Yii::info()]]: registra un mensaje que transmite información útil.
* [[Yii::warning()]]: registra un mensaje de advertencia que indica que ha sucedido algo inesperado.
* [[Yii::error()]]: registra un error fatal que debe ser investigado tan pronto como sea posible.
Estos métodos registran mensajes de varios *niveles de severidad* y *categorías*. Comparten el mismo registro de
función `function ($message, $category = 'application')`, donde `$message` representa el mensaje del registro que
tiene que ser registrado, mientras que `$category` es la categoría del registro de mensaje. El código del siguiente
ejemplo registra la huella del mensaje para la categoría `application`:
```php
Yii::trace('start calculating average revenue');
```
> Información: Los mensajes de registro pueden ser tanto cadenas de texto como datos complejos, como arrays o objetos.
Es responsabilidad de los [destinos de registros](#log-targets) tratar los mensajes de registro de manera apropiada.
De forma predeterminada, si un mensaje de registro no es una cadena de texto, se exporta como si fuera un string
llamando a [[yii\helpers\VarDumper::export()]].
Para organizar mejor y filtrar los mensajes de registro, se recomienda especificar una categoría apropiada para cada
mensaje de registro. Se puede elegir un sistema de nombres jerárquicos por categorías que facilite a los
[destino de registros](#log-targets) el filtrado de mensajes basándose en categorías. Una manera simple pero
efectiva de organizarlos es usar la constante predefinida (magic constant) de PHP `__METHOD__` como nombre de
categoría. Además este es el enfoque que se usa en el código del núcleo (core) del framework Yii. Por ejemplo,
```php
Yii::trace('start calculating average revenue', __METHOD__);
```
La constante `__METHOD__` equivale al nombre del método (con el prefijo del nombre completo del nombre de clase) donde
se encuentra la constante. Por ejemplo, es igual a la cadena `'app\controllers\RevenueController::calculate'` si la
linea anterior de código se llamara dentro de este método.
> Información: Los métodos de registro de anotaciones descritos anteriormente en realidad son accesos directos al
método [[yii\log\Logger::log()|log()]] del [[yii\log\Logger|logger object]] que es un singleton accesible a través
de la expresión `Yii::getLogger()`. Cuando se hayan registrado suficientes mensajes o cuando la aplicación haya
finalizado, el objeto de registro llamará [[yii\log\Dispatcher|message dispatcher]] para enviar los mensajes de
registro registrados a los [destiinos de registros](#log-targets).
## Destino de Registros <a name="log-targets"></a>
Un destino de registro es una instancia de la clase [[yii\log\Target]] o de una clase hija. Este filtra los
mensajes de registro por sus niveles de severidad y sus categorías y después los exporta a algún medio. Por ejemplo,
un [[yii\log\DbTarget|database target]] exporta los mensajes de registro filtrados a una tabla de base de datos,
mientras que un [[yii\log\EmailTarget|email target]] exporta los mensajes de registro a una dirección de correo electrónico específica.
Se pueden registrar múltiples destinos de registros en una aplicación configurándolos en la
[aplicación de componente ](structure-application-components.md) `log` dentro de la configuración de aplicación, como
en el siguiente ejemplo:
```php
return [
// el componente log tiene que cargarse durante el proceso de bootstrapping
'bootstrap' => ['log'],
'components' => [
'log' => [
'targets' => [
[
'class' => 'yii\log\DbTarget',
'levels' => ['error', 'warning'],
],
[
'class' => 'yii\log\EmailTarget',
'levels' => ['error'],
'categories' => ['yii\db\*'],
'message' => [
'from' => ['log@example.com'],
'to' => ['admin@example.com', 'developer@example.com'],
'subject' => 'Database errors at example.com',
],
],
],
],
],
];
```
> Nota: El componente `log` debe cargarse durante el proceso de [bootstrapping](runtime-bootstrapping.md) para que
pueda enviar los mensajes de registro a los destinos inmediatamente. Este es el motivo por el que se lista en el
array `bootstrap` como se muestra más arriba.
En el anterior código, se registran dos destinos de registros en la propiedad [[yii\log\Dispatcher::targets]]
* el primer destino gestiona los errores y las advertencias y las guarda en una tabla de la base de datos;
* el segundo destino gestiona mensajes los mensajes de error de las categorías cuyos nombres empiecen por
`yii\db\` y los envía por email a las direcciones `admin@example.com` y `developer@example.com`.
Yii incluye los siguientes destinos. En la API de documentación se pueden referencias a estas clases e
información de configuración y uso.
* [[yii\log\DbTarget]]: almacena los mensajes de registro en una tabla de la base de datos.
* [[yii\log\EmailTarget]]: envía los mensajes de registro a direcciones de correo preestablecidas.
* [[yii\log\FileTarget]]: guarda los menajes de registro en archivos.
* [[yii\log\SyslogTarget]]: guarda los mensajes de registro en el syslog llamando a la función PHP `syslog()`.
A continuación, se describirá las características más comunes de todos los destinos de registros.
### Filtrado de Mensajes <a name="message-filtering"></a>
Se pueden configurar las propiedades [[yii\log\Target::levels|levels]] y [[yii\log\Target::categories|categories]] para
cada destino de registros, con estas se especifican los niveles de severidad y las categorías de mensajes que
deberán procesar sus destinos.
La propiedad [[yii\log\Target::levels|levels]] es un array que consta de uno o varios de los siguientes valores:
* `error`: correspondiente a los mensajes registrados por [[Yii::error()]].
* `warning`: correspondiente a los mensajes registrados por [[Yii::warning()]].
* `info`: correspondiente a los mensajes registrados por [[Yii::info()]].
* `trace`: correspondiente a los mensajes registrados por [[Yii::trace()]].
* `profile`: correspondiente a los mensajes registrados por [[Yii::beginProfile()]] y [[Yii::endProfile()]], que se
explicara más detalladamente en la subsección [Perfiles](#performance-profiling).
Si no se especifica la propiedad [[yii\log\Target::levels|levels]], significa que el destino procesará los
mensajes de *cualquier* nivel de severidad.
La propiedad [[yii\log\Target::categories|categories]] es un array que consta de categorías de mensaje o patrones. El
destino sólo procesará mensajes de las categorías que se puedan encontrar o si coinciden con algún patrón listado
en el array. Un patrón de categoría es un nombre de categoría al que se le añade un asterisco `*` al final. Un nombre
de categoría coincide con un patrón si empieza por el mismo prefijo que el patrón. Por ejemplo,
`yii\db\Command::execute` y `yii\db\Command::query` que se usan como nombres de categoría para los mensajes
registrados en la clase [[yii\db\Command]], coinciden con el patrón `yii\db\*`.
Si no se especifica la propiedad [[yii\log\Target::categories|categories]], significa que el destino procesará
los mensajes de *todas* las categorías.
Además añadiendo las categorías en listas blancas (whitelisting) mediante la propiedad
[[yii\log\Target::categories|categories]], también se pueden añadir ciertas categorías en listas negras (blacklist)
configurando la propiedad [[yii\log\Target::except|except]]. Si se encuentra la categoría de un mensajes o coincide
algún patrón con esta propiedad, NO será procesada por el destino.
La siguiente configuración de destinos especifica que el destino solo debe procesar los mensajes de error y
de advertencia de las categorías que coincidan con alguno de los siguientes patrones `yii\db\*` o
`yii\web\HttpException:*`, pero no con `yii\web\HttpException:404`.
```php
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning'],
'categories' => [
'yii\db\*',
'yii\web\HttpException:*',
],
'except' => [
'yii\web\HttpException:404',
],
]
```
> Información: Cuando se captura una excepción de tipo HTTP por el [gestor de errores](runtime-handling-errors.md), se
registrará un mensaje de error con el nombre de categoría con formato `yii\web\HttpException:ErrorCode`. Por
ejemplo, la excepción [[yii\web\NotFoundHttpException]] causará un mensaje de error del tipo
`yii\web\HttpException:404`.
### Formato de los Mensajes <a name="message-formatting"></a>
Los destinos exportan los mensajes de registro filtrados en cierto formato. Por ejemplo, is se instala un
destino de registros de la calse [[yii\log\FileTarget]], encontraremos un registro similar en el archivo de
registro `runtime/log/app.log`:
```
2014-10-04 18:10:15 [::1][][-][trace][yii\base\Module::getModule] Loading module: debug
```
De forma predeterminada los mensajes de registro se formatearan por [[yii\log\Target::formatMessage()]] como en el
siguiente ejemplo:
```
Timestamp [IP address][User ID][Session ID][Severity Level][Category] Message Text
```
Se puede personalizar el formato configurando la propiedad [[yii\log\Target::prefix]] que es un PHP ejecutable y
devuelve un prefijo de mensaje personalizado. Por ejemplo, el siguiente código configura un destino de registro
anteponiendo a cada mensaje de registro el ID de usuario (se eliminan la dirección IP y el ID por razones de
privacidad).
```php
[
'class' => 'yii\log\FileTarget',
'prefix' => function ($message) {
$user = Yii::$app->has('user', true) ? Yii::$app->get('user') : null;
$userID = $user ? $user->getId(false) : '-';
return "[$userID]";
}
]
```
Además de prefijos de mensaje, destinos de registros también añaden alguna información de contexto en cada lote
de mensajes de registro. De forma predeterminada, se incluyen los valores de las siguientes variables globales de
PHP: `$_GET`, `$_POST`, `$_FILES`, `$_COOKIE`, `$_SESSION` y `$_SERVER`. Se puede ajustar el comportamiento
configurando la propiedad [[yii\log\Target::logVars]] con los nombres de las variables globales que se quieran incluir
con el destino del registro. Por ejemplo, la siguiente configuración de destino de registros especifica que
sólo se añadirá al mensaje de registro el valor de la variable `$_SERVER`.
```php
[
'class' => 'yii\log\FileTarget',
'logVars' => ['_SERVER'],
]
```
Se puede configurar `logVars` para que sea un array vacío para deshabilitar totalmente la inclusión de información de
contexto. O si se desea implementar un método propio de proporcionar información de contexto se puede sobrescribir el
método [[yii\log\Target::getContextMessage()]].
### Nivel de Seguimiento de Mensajes <a name="trace-level"></a>
Durante el desarrollo, a veces se quiere visualizar de donde proviene cada mensaje de registro. Se puede lograr
configurando la propiedad [[yii\log\Dispatcher::traceLevel|traceLevel]] del componente `log` como en el siguiente
ejemplo:
```php
return [
'bootstrap' => ['log'],
'components' => [
'log' => [
'traceLevel' => YII_DEBUG ? 3 : 0,
'targets' => [...],
],
],
];
```
La configuración de aplicación anterior establece el [[yii\log\Dispatcher::traceLevel|traceLevel]] para que sea 3 si
`YII_DEBUG` esta habilitado y 0 si esta deshabilitado. Esto significa que si `YII_DEBUG` esta habilitado, a cada
mensaje de registro se le añadirán como mucho 3 niveles de la pila de llamadas del mensaje que se este registrando; y
si `YII_DEBUG` está deshabilitado, no se incluirá información de la pila de llamadas.
> Información: Obtener información de la pila de llamadas no es trivial. Por lo tanto, sólo se debe usar esta
características durante el desarrollo o cuando se depura la aplicación.
### Liberación (Flushing) y Exportación de Mensajes <a name="flushing-exporting"></a>
Como se ha comentado anteriormente, los mensajes de registro se mantienen en un array por el
[[yii\log\Logger|logger object]]. Para limitar el consumo de memoria de este array, el componente encargado del
registro de mensajes enviará los mensajes registrados a los [destinos de registros](#log-targets) cada vez que el
array acumule un cierto número de mensajes de registro. Se puede personalizar el número configurando la propiedad
[[yii\log\Dispatcher::flushInterval|flushInterval]] del componente `log`:
```php
return [
'bootstrap' => ['log'],
'components' => [
'log' => [
'flushInterval' => 100, // el valor predeterminado es 1000
'targets' => [...],
],
],
];
```
> Información: También se produce la liberación de mensajes cuando la aplicación finaliza, esto asegura que los
destinos de los registros reciban los mensajes de registro.
Cuando el [[yii\log\Logger|logger object]] libera los mensajes de registro enviándolos a los
[destinos de registros](#log-targets), estos no se exportan inmediatamente. La exportación de mensajes solo se
produce cuando un destino de registros acumula un cierto número de mensajes filtrados. Se puede personalizar este
número configurando la propiedad [[yii\log\Target::exportInterval|exportInterval]] de un
[destinos de registros](#log-targets) individual, como se muestra a continuación,
```php
[
'class' => 'yii\log\FileTarget',
'exportInterval' => 100, // el valor predeterminado es 1000
]
```
Debido al nivel de configuración de la liberación y exportación de mensajes, de forma predeterminada cuando se llama a
`Yii::trace()` o cualquier otro método de registro de mensajes, NO veremos el registro de mensaje inmediatamente en
los destinos de registros. Esto podría ser un problema para algunas aplicaciones de consola de ejecución
prolongada (long-running). Para hacer que los mensajes de registro aparezcan inmediatamente en los destinos de
registro se deben establecer [[yii\log\Dispatcher::flushInterval|flushInterval]] y
[[yii\log\Target::exportInterval|exportInterval]] para que tengan valor 1 como se muestra a continuación:
```php
return [
'bootstrap' => ['log'],
'components' => [
'log' => [
'flushInterval' => 1,
'targets' => [
[
'class' => 'yii\log\FileTarget',
'exportInterval' => 1,
],
],
],
],
];
```
> Nota: El uso frecuente de liberación y exportación puede degradar el rendimiento de la aplicación.
### Conmutación de Destinos de Registros <a name="toggling-log-targets"></a>
Se puede habilitar o deshabilitar un destino de registro configuración su propiedad
[[yii\log\Target::enabled|enabled]]. Esto se puede llevar a cabo a mediante la configuración del destino de
registros o con la siguiente declaración PHP de código:
```php
Yii::$app->log->targets['file']->enabled = false;
```
El código anterior requiere que se asocie un destino como `file`, como se muestra a continuación usando las
claves de texto en el array `targets`:
```php
return [
'bootstrap' => ['log'],
'components' => [
'log' => [
'targets' => [
'file' => [
'class' => 'yii\log\FileTarget',
],
'db' => [
'class' => 'yii\log\DbTarget',
],
],
],
],
];
```
### Creación de Nuevos Destinos <a name="new-targets"></a>
La creación de nuevas clases de destinos de registro es muy simple. Se necesita implementar el método
[[yii\log\Target::export()]] enviando el contenido del array [[yii\log\Target::messages]] al medio designado. Se puede
llamar al método [[yii\log\Target::formatMessage()]] para formatear los mensajes. Se pueden encontrar más detalles de
destinos de registros en las clases incluidas en la distribución de Yii.
## Perfilado de Rendimiento <a name="performance-profiling"></a>
El Perfilado de rendimiento es un tipo especial de registro de mensajes que se usa para medir el tiempo que tardan en
ejecutarse ciertos bloques de código y encontrar donde están los cuellos de botella de rendimiento. Por ejemplo, la
clase [[yii\db\Command]] utiliza el perfilado de rendimiento para encontrar conocer el tiempo que tarda cada consulta
a la base de datos.
Para usar el perfilado de rendimiento, primero debemos identificar los bloques de código que tienen que ser
perfilados, para poder enmarcar su contenido como en el siguiente ejemplo:
```php
\Yii::beginProfile('myBenchmark');
... Empieza el perfilado del bloque de código ...
\Yii::endProfile('myBenchmark');
```
Donde `myBenchmark` representa un token único para identificar el bloque de código. Después cuando se examine el
resulte del perfilado, se podrá usar este token para encontrar el tiempo que ha necesitado el correspondiente bloque
de código.
Es importante asegurarse de que los pares de `beginProfile` y `endProfile` estén bien anidados. Por ejemplo,
```php
\Yii::beginProfile('block1');
// código que será perfilado
\Yii::beginProfile('block2');
// más código para perfilar
\Yii::endProfile('block2');
\Yii::endProfile('block1');
```
Si nos dejamos el `\Yii::endProfile('block1')` o lo intercambiamos `\Yii::endProfile('block1')` con
`\Yii::endProfile('block2')`, el perfilado de rendimiento no funcionará.
Se registra un mensaje de registro con el nivel de severidad `profile` para cada bloque de código que se haya
perfilado. Se puede configurar el [destino del registro](#log-targets) para reunir todos los mensajes y exportarlos.
El [depurador de Yii](tool-debugger.md) incluye un panel de perfilado de rendimiento que muestra los resultados de
perfilado.
Генерация кода при помощи Gii
========================
В этом разделе, мы опишем как использовать [Gii](tool-gii.md) для автоматической генерации кода
реализующий некоторые общие особенности. Для достижения этой цели, все что вам нужно это просто ввести необходимую информацию в соответствии с инструкциями отображаемыми на веб-страницах Gii.
В этом разделе мы опишем, как использовать [Gii](tool-gii.md) для автоматической генерации кода,
реализующего некоторые общие функции вебсайта. Для достижения этой цели всё, что вам нужно, это просто ввести необходимую информацию в соответствии с инструкциями, отображаемыми на веб-страницах Gii.
В этом руководстве, вы узнаете
В этом руководстве вы узнаете:
* Как включить Gii в приложении;
* Как активировать Gii в приложении;
* Как использовать Gii для создания Active Record класса;
* Как использовать Gii для генерации кода, реализующего CRUD для таблицы БД.
* Как настроить код генерируемый Gii.
* Как настроить код, генерируемый Gii.
Запускаем Gii <a name="starting-gii"></a>
------------
[Gii](tool-gii.md) поставляется в Yii как [модуль](structure-modules.md). Вы можете включить Gii
настроив его свойство [[yii\base\Application::modules|modules]] приложения. В частности, вы можете найти следующий код уже приведен в `config/web.php` файле - настройки приложения,
[Gii](tool-gii.md) предствален в Yii как [модуль](structure-modules.md). Вы можете активировать Gii,
настроив его в свойстве [[yii\base\Application::modules|modules]]. В зависимости от того, каким образом вы создали приложение, вы можете удостовериться в наличии следующего кода в конфигурационном файле `config/web.php`,
```php
$config = [ ... ];
......@@ -27,92 +27,100 @@ if (YII_ENV_DEV) {
}
```
Приведенная выше конфигурация показывает, что когда в [среде разработки](concept-configurations.md#environment-constants),
Приведенная выше конфигурация показывает, что находясь в [режиме разработки](concept-configurations.md#environment-constants),
приложение должно включать в себя модуль с именем `gii`, который реализует класс [[yii\gii\Module]].
Если вы проверите [входной скрипт](structure-entry-scripts.md) `web/index.php` вашего приложения, вы
найдете следующую строку, которая по сути делает `YII_ENV_DEV`, чтобы быть правдой.
Если вы посмотрите [входной скрипт](structure-entry-scripts.md) `web/index.php` вашего приложения, вы
увидите следующую строку, устанавливающую константу `YII_ENV_DEV` в значение `true`.
```php
defined('YII_ENV') or define('YII_ENV', 'dev');
```
Благодаря этой строке, ваше приложение находится в режиме разработки, и Gii будет уже включен, в соответствии с описанной выше конфигурации. Теперь вы можете получить доступ к Gii по следующему адресу:
Благодаря этой строке ваше приложение находится в режиме разработки, и Gii уже активирован в соответствии с описанной выше конфигурацией. Теперь вы можете получить доступ к Gii по следующему адресу:
```
http://hostname/index.php?r=gii
```
> Замечание: Если вы пытаетесь получить доступ к Gii не с локального хоста, по умолчанию, в целях обеспечения безопасности,
> доступ будет запрещён. Вы можете изменить настройки Gii, чтобы добавить разрешённые IP адреса, как указано ниже
```php
'gii' => [
'class' => 'yii\gii\Module',
'allowedIPs' => ['127.0.0.1', '::1', '192.168.0.*', '192.168.178.20'] // регулируйте в соответствии со своими нуждами
],
```
![Gii](images/start-gii.png)
Генерация класса Active Record <a name="generating-ar"></a>
---------------------------------
Для использования Gii генератора класса Active Record, выберите "Генератор модели" (нажав на ссылку на главной странице Gii). И заполните форму следующим образом:
Чтобы использовать Gii для генерации класса Active Record, выберите "Генератор модели" (нажав на ссылку на главной странице Gii). И заполните форму следующим образом:
* Имя таблицы: `country`
* Класс модели : `Country`
![Генератор модели](images/start-gii-model.png)
Затем нажмите на кнопку "Предварительный просмотр". Вы увидите `models/Country.php` перечислен в результатах файл класса, который будет создан. Вы можете нажать на имя файла класса, для просмотра его содержимого.
Затем нажмите на кнопку "Предварительный просмотр". Вы увидите, что `models/Country.php` перечислен в результатах создаваемых файлов классов. Вы можете нажать на имя файла класса для просмотра его содержимого.
При использовании Gii, если вы уже создали такой же файл и хотите перезаписать его, нажмите кнопку `различия` рядом с именем файла, чтобы увидеть различия между генерируемого кода и существующей версии.
Если вы уже создали такой же файл и хотите перезаписать его, нажмите кнопку `diff` рядом с именем файла, чтобы увидеть различия между генерируемым кодом и существующей версией.
![Предварительный просмотр генератора модели](images/start-gii-model-preview.png)
Если необходимо перезаписать существующего файла, установите флажок рядом с "переписать", а затем нажмите кнопку "Создать". При создании нового файла, вы можете просто нажать "Создать".
Для перезаписи существующего файла установите флажок рядом с "overwrite" и нажмите кнопку "Generate". Для создания нового файла вы можете просто нажать "Generate".
Далее, вы увидите страницу подтверждения, указывающую что код был успешно создана. Если ваш файл уже существует, вы также увидите сообщение о том, что он был переписан с вновь сгенерированным кодом.
После этого вы увидите страницу подтверждения, указывающую на то, что код был успешно сгенерирован. Если файл существовал до этого, вы также увидите сообщение о том, что он был перезаписан заново сгенерированным кодом.
Создание CRUD кода <a name="generating-crud"></a>
--------------------
CRUD расшифровывается как Создать, Читать, Обновить, и Удалить, представляющих четыре общие задачи, принятые с данными на большинстве веб-сайтов. Чтобы создать функциональность CRUD используйте Gii, выберите "CRUD Генератор" (нажав на ссылку на главной странице GII). Для «country», например, заполнить полученную форму следующим образом:
CRUD расшифровывается как Create, Read, Update и Delete, предоставляющий четыре основные функции, выполняемые над данными на большинстве веб-сайтов. Чтобы создать функциональность CRUD используя Gii, выберите "CRUD Генератор" (нажав на ссылку на главной странице Gii). Для нашей таблицы «country» заполните полученную форму следующим образом:
* Класс модели : `app\models\Country`
* Класс модели поиска: `app\models\CountrySearch`
* Класс контроллера: `app\controllers\CountryController`
* Model Class: `app\models\Country`
* Search Model Class: `app\models\CountrySearch`
* Controller Class: `app\controllers\CountryController`
![CRUD генератор](images/start-gii-crud.png)
Затем, нажмите на кнопку "Предварительный просмотр". Вы увидите список файлов, которые будут созданы, как показано ниже.
Затем нажмите на кнопку "Preview". Вы увидите список файлов, которые будут созданы, как показано ниже.
[[ЗДЕСЬ НУЖНА КАРТИНКА]]
![CRUD генератор: предпросмотр](images/start-gii-crud-preview.png)
Если вы ранее создали `controllers/CountryController.php` и `views/country/index.php` файлы (в разделе базы данных направляющей), установите флажок "переписать", чтобы заменить их. (Предыдущие версии не имеют полной поддержку CRUD.)
Если вы уже создали файлы `controllers/CountryController.php` и `views/country/index.php` (в разделе о базах данных), установите флажок "overwrite", чтобы заменить их. (Предыдущие версии не поддерживают CRUD полностью)
Пытается его <a name="trying-it-out"></a>
Испытываем в действии <a name="trying-it-out"></a>
-------------
Чтобы увидеть как она работает, используйте ваш браузер для доступа к следующему URL:
Чтобы увидеть как всё это работает, перейдите по следующему URL, используя ваш браузер:
```
http://hostname/index.php?r=country/index
```
Вы увидите таблицу данных, показывающую страны из таблицы базы данных. Вы можете сортировать, или фильтр необходимо ввести условия фильтрации в заголовки столбцов.
Вы увидите таблицу, показывающую страны из таблицы БД. Вы можете сортировать, а также фильтровать данные, указывая условия фильтрации в заголовках столбцов.
Для каждой страны отображающейся в таблице, вы можете просмотреть подробную информацию, обновить ее или удалить.
Вы также можете нажать на кнопку "Создать страну" в верхней части таблицы и будет предоставлена форма для создания новой страны.
Для каждой отображающейся в таблице страны вы можете просмотреть подробную информацию, обновить или удалить её.
Вы также можете нажать на кнопку "Создать страну" в верхней части таблицы для получения формы создания новой страны.
![Таблица данных стран](images/start-gii-country-grid.png)
![Обновление страны](images/start-gii-country-update.png)
Ниже приведен список файлов созданных с помощью Gii, в случае если вы хотите исследовать эту реализацию функций, или их настройки:
Ниже приведен список файлов, созданных с помощью Gii, в том случае, если вы захотите исследовать реализацию этих функций, или изменить их:
* Контроллер: `controllers/CountryController.php`
* Модели: `models/Country.php` and `models/CountrySearch.php`
* Модели: `models/Country.php` и `models/CountrySearch.php`
* Вид: `views/country/*.php`
> Информация: Gii разработан как высоко настраиваемый и расширяемый инструмент генерации кода. Используя его с умом может значительно ускорить скорость разработки приложений. Для более подробной информации, пожалуйста обратитесь к разделу [Gii](tool-gii.md).
> Информация: Gii разработан как тонконастраиваемый и расширяемый инструмент генерации кода. Используя его с умом, вы можете значительно ускорить скорость разработки приложений. Для более подробной информации, пожалуйста, обратитесь к разделу [Gii](tool-gii.md).
Заключение <a name="summary"></a>
-------
В этом разделе, Вы узнали как использовать Gii чтобы генерировать код который реализует полный функциональность CRUD для содержимого которое хранится в таблице базы данных.
В этом разделе вы узнали, как использовать Gii для генерации кода, реализующего полную функциональность CRUD для данных, хранящихся в таблице базы данных.
......@@ -24,7 +24,7 @@ All Rights Reserved.
* [Робота з формами](start-forms.md)
* [Робота з базами даних](start-databases.md)
* [Генерація коду за допомогою Gii](start-gii.md)
* [Що далі?](start-looking-ahead.md)
* [Наступні кроки](start-looking-ahead.md)
Структура додатка
......@@ -35,24 +35,24 @@ All Rights Reserved.
* [Додатки](structure-applications.md)
* [Компоненти додатка](structure-application-components.md)
* [Контролери](structure-controllers.md)
* [Представлення](structure-views.md)
* [Моделі](structure-models.md)
* **TBD** [Фільтри](structure-filters.md)
* **TBD** [Віджети](structure-widgets.md)
* **TBD** [Модулі](structure-modules.md)
* [Представлення](structure-views.md)
* [Модулі](structure-modules.md)
* [Фільтри](structure-filters.md)
* [Віджети](structure-widgets.md)
* [Ресурси](structure-assets.md)
* **TBD** [Розширення](structure-extensions.md)
* [Розширення](structure-extensions.md)
Обробка запитів
---------------
* **TBD** [Bootstrapping](runtime-bootstrapping.md)
* **TBD** [Роутінг](runtime-routing.md)
* **TBD** [Запити](runtime-requests.md)
* **TBD** [Відповіді](runtime-responses.md)
* **TBD** [Сесії та кукі](runtime-sessions-cookies.md)
* [Розбір та генерація URL](runtime-url-handling.md)
* [Огляд](runtime-overview.md)
* [Bootstrapping](runtime-bootstrapping.md)
* [Роутінг та створення URL](runtime-routing.md)
* [Запити](runtime-requests.md)
* [Відповіді](runtime-responses.md)
* [Сесії та кукі](runtime-sessions-cookies.md)
* [Обробка помилок](runtime-handling-errors.md)
* [Логування](runtime-logging.md)
......@@ -74,10 +74,10 @@ All Rights Reserved.
Робота з базами даних
---------------------
* [Обʼєкти доступу до даних (DAO)](db-dao.md) - Зʼєднання з базою даних, прості запити, транзакції і робота зі схемою.
* [Конструктор запитів](db-query-builder.md) - Запити до бази даних через простий шар абстракції.
* [Active Record](db-active-record.md) - Отримання обʼєктів AR, робота з ними та визначення звʼязків.
* [Міграції](db-migrations.md) - Контроль версій схеми даних при роботі в команді.
* [Обʼєкти доступу до даних (DAO)](db-dao.md) - Зʼєднання з базою даних, прості запити, транзакції і робота зі схемою
* [Конструктор запитів](db-query-builder.md) - Запити до бази даних через простий шар абстракції
* [Active Record](db-active-record.md) - Отримання обʼєктів AR, робота з ними та визначення звʼязків
* [Міграції](db-migrations.md) - Контроль версій схеми даних при роботі в команді
* **TBD** [Sphinx](db-sphinx.md)
* **TBD** [Redis](db-redis.md)
* **TBD** [MongoDB](db-mongodb.md)
......@@ -88,19 +88,20 @@ All Rights Reserved.
-------------------------------
* [Створення форм](input-forms.md)
* [Валідація](input-validation.md)
* **TBD** [Завантаження файлів](input-file-uploading.md)
* [Валідація вводу](input-validation.md)
* [Завантаження файлів](input-file-uploading.md)
* **TBD** [Робота з декількома моделями](input-multiple-models.md)
Відображення даних
------------------
* **TBD** [Форматування даних](output-formatting.md)
* [Форматування даних](output-formatter.md)
* **TBD** [Посторінкове розбиття](output-pagination.md)
* **TBD** [Сортування](output-sorting.md)
* [Провайдери даних](output-data-providers.md)
* [Віджети для даних](output-data-widgets.md)
* [Віджети даних](output-data-widgets.md)
* [Робота з клієнтськими скриптами](output-client-scripts.md)
* [Темізація](output-theming.md)
......@@ -118,14 +119,14 @@ All Rights Reserved.
---------
* [Огляд](caching-overview.md)
* [Кешуванная даних](caching-data.md)
* [Кешуванная фрагментів](caching-fragment.md)
* [Кешуванная сторінок](caching-page.md)
* [HTTP кешуванная](caching-http.md)
* [Кешування даних](caching-data.md)
* [Кешування фрагментів](caching-fragment.md)
* [Кешування сторінок](caching-page.md)
* [HTTP кешування](caching-http.md)
Веб-сервіси REST
----------------
RESTful веб-сервіси
-------------------
* [Швидкий старт](rest-quick-start.md)
* [Ресурси](rest-resources.md)
......@@ -133,7 +134,7 @@ All Rights Reserved.
* [Роутінг](rest-routing.md)
* [Форматування відповіді](rest-response-formatting.md)
* [Аутентифікація](rest-authentication.md)
* [Обмеження кількості запитів](rest-rate-limiting.md)
* [Обмеження частоти запитів](rest-rate-limiting.md)
* [Версіонування](rest-versioning.md)
* [Обробка помилок](rest-error-handling.md)
......@@ -150,57 +151,49 @@ All Rights Reserved.
----------
* [Огляд](test-overview.md)
* **TBD** [Модульні тести](test-unit.md)
* **TBD** [Функціональні тести](test-functional.md)
* **TBD** [Приймальні тести](test-acceptance.md)
* [Налаштування середовища тестування](test-environment-setup.md)
* [Модульні тести](test-unit.md)
* [Функціональні тести](test-functional.md)
* [Приймальні тести](test-acceptance.md)
* [Фікстури](test-fixtures.md)
Розширення Yii
--------------
* [Створення розширень](extend-creating-extensions.md)
* [Розширення коду фреймворку](extend-customizing-core.md)
* [Використання сторонніх бібліотек](extend-using-libs.md)
* **TBD** [Інтеграція Yii в сторонні системи](extend-embedding-in-others.md)
* **TBD** [Одночасне використання Yii 1.1 та 2.0](extend-using-v1-v2.md)
* [Використання Composer](extend-using-composer.md)
Спеціальні теми
---------------
* [Шаблон додатка advanced](tutorial-advanced-app.md)
* [Розширений шаблон додатка](tutorial-advanced-app.md)
* [Створення додатка з нуля](tutorial-start-from-scratch.md)
* [Консольні команди](tutorial-console.md)
* [Основні валідатори](tutorial-core-validators.md)
* [Інтернаціонализація](tutorial-i18n.md)
* [Відправка пошти](tutorial-mailing.md)
* [Робота з поштою](tutorial-mailing.md)
* [Вдосконалення продуктивності](tutorial-performance-tuning.md)
* **TBD** [Робота на shared хостингу](tutorial-shared-hosting.md)
* [Робота на shared хостингу](tutorial-shared-hosting.md)
* [Шаблонізатори](tutorial-template-engines.md)
* [Робота із стороннім кодом](tutorial-yii-integration.md)
Віджети
-------
* GridView: link to demo page
* ListView: link to demo page
* DetailView: link to demo page
* ActiveForm: link to demo page
* Pjax: link to demo page
* Menu: link to demo page
* LinkPager: link to demo page
* LinkSorter: link to demo page
* [Віджети Bootstrap](bootstrap-widgets.md)
* **TBD** [Віджети Jquery UI](jui-widgets.md)
* GridView: **TBD** link to demo page
* ListView: **TBD** link to demo page
* DetailView: **TBD** link to demo page
* ActiveForm: **TBD** link to demo page
* Pjax: **TBD** link to demo page
* Menu: **TBD** link to demo page
* LinkPager: **TBD** link to demo page
* LinkSorter: **TBD** link to demo page
* [Віджети Bootstrap](widget-bootstrap.md)
* [Віджети Jquery UI](widget-jui.md)
Хелпери
-------
* [Огляд](helper-overview.md)
* **TBD** [ArrayHelper](helper-array.md)
* [ArrayHelper](helper-array.md)
* **TBD** [Html](helper-html.md)
* **TBD** [Url](helper-url.md)
* [Url](helper-url.md)
* **TBD** [Security](helper-security.md)
Кешування фрагментів
================
====================
Кешування фрагментів відноситься до кешуванню фрагментів сторінки. Наприклад, якщо сторінка відображає в таблиці сумарні річні продажі, ми можемо зберегти цю таблицю в кеші з метою економії часу, необхідного для створення таблиці при кожному запиті. Кешування фрагментів засноване на [кешуванні даних](caching-data.md).
Кешування фрагментів відноситься до кешування фрагментів веб-сторінки. Наприклад, якщо сторінка відображає в таблиці сумарні
річні продажі, ви можете зберегти цю таблицю в кеші з метою економії часу, необхідного для створення таблиці при кожному запиті.
Кешування фрагментів засноване на [кешуванні даних](caching-data.md).
Для кешування фрагментів використовуйте наступний код в [виді](structure-views.md):
Для кешування фрагментів використовуйте наступний код у [представленні](structure-views.md):
```php
if ($this->beginCache($id)) {
// ... тут створюємо вміст ...
// ... тут створюємо зміст ...
$this->endCache();
}
```
Таким чином укладіть те, що ви хочете закешовану між викликом [[yii\base\View::beginCache()|beginCache()]] та
[[yii\base\View::endCache()|endCache()]]. Якщо вміст буде знайдено в кеші, [[yii\base\View::beginCache()|beginCache()]]
відобразить закешований вміст і поверне false, минаючи генерацію вмісту.
В іншому випадку, буде виконаний код генерації контента і коли буде викликаний [[yii\base\View::endCache()|endCache()]], то сгенерированное вміст буде записано і збережено в кеші.
Таким чином, розташуйте логіку генерації вмісту у комбінацію викликів [[yii\base\View::beginCache()|beginCache()]] та
[[yii\base\View::endCache()|endCache()]]. Якщо вміст буде знайдено у кеші, [[yii\base\View::beginCache()|beginCache()]]
відобразить закешований вміст і поверне false, оминаючи генерацію вмісту.
В іншому випадку, буде виконано логіку генерації вмісту і з викликом [[yii\base\View::endCache()|endCache()]]
згенерований вміст буде записаний до кешу.
Также как и [кэширование данных](caching-data.md), для кэширования фрагментов требуется уникальный идентификатор для определения кэшируемого фрагмента.
Подібно до [кешування даних](caching-data.md), для кешування фрагментів необхідний унікальний ідентифікатор
для визначення кешувального фрагмента.
## Параметры кэширования <a name="caching-options"></a>
## Параметри кешування <a name="caching-options"></a>
Вызывая метод [[yii\base\View::beginCache()|beginCache()]], мы можем передать в качестве второго аргумента массив, содержащий параметры кэширования для управления кэшированием фрагмента. Заглядывая за кулисы, можно увидеть, что этот массив будет использоваться для настройки виджета [[yii\widgets\FragmentCache]], который реализует фактическое кэширование фрагментов.
Ви можете вказати додаткові параметри про кешуванні фрагментів, передавши масив опцій в якості другого параметра метода
[[yii\base\View::beginCache()|beginCache()]]. За лаштунками, цей масив параметрів буде використано для налаштування віджета
[[yii\widgets\FragmentCache]], який реалізує фактичну функціональність кешування фрагментів.
### Срок хранения <a name="duration"></a>
Наверное, наиболее часто используемым параметром является [[yii\widgets\FragmentCache::duration|duration]].
Он определяет какое количество секунд содержимое будет оставаться действительным (корректным). Следующий код помещает фрагмент в кэш не более, чем на час::
### Тривалість <a name="duration"></a>
Мабуть найбільш часто використовуваною опцією кешування фрагмента є [[yii\widgets\FragmentCache::duration|duration]].
Вона визначає на скільки секунд зміст може залишатися дійсним у кеші. Код нижче кешує фрагмент не більше, ніж на одну:
```php
if ($this->beginCache($id, ['duration' => 3600])) {
// ... здесь создаём содержимое ...
// ... тут створюємо зміст ...
$this->endCache();
}
```
Если мы не установим длительность (срок хранения), она будет равна значению по умолчанию (60 секунд). Это значит, что кэшированное содержимое станет недействительным через 60 секунд.
Якщо опцію тривалості не задано, то вона прийме значенне за замовчування (60), що означає, що вміст в кеші стане недійсним через 60 секунд.
### Зависимости <a name="dependencies"></a>
### Залежності <a name="dependencies"></a>
Также как и [кэширование данных](caching-data.md#cache-dependencies), кэшируемое содержимое фрагмента тоже может иметь зависимости. Например, отображение содержимого сообщения зависит от того, изменено или нет это сообщение.
Подібно до [кешування даних](caching-data.md#cache-dependencies), фрагмент вмісту у кеші також може мати залежності.
Наприклад, вміст поста, що відображається, залежить від того, чи був він змінений.
Для определения зависимости мы устанавливаем параметр [[yii\widgets\FragmentCache::dependency|dependency]], который может быть либо объектом [[yii\caching\Dependency]], либо массивом настроек, который может быть использован для создания объекта [[yii\caching\Dependency]]. Следующий код определяет содержимое фрагмента, зависящее от изменения значения столбца `updated_at`:
Для визначення залежності, встановіть опцію [[yii\widgets\FragmentCache::dependency|dependency]],
яка може бути або обʼєктом [[yii\caching\Dependency]] або масивом налаштувань для створення обʼєкта залежностей.
Наступний код визначає, що вміст фрагмента залежить від зміни значення стовпця `updated_at`:
```php
$dependency = [
......@@ -57,91 +67,109 @@ $dependency = [
if ($this->beginCache($id, ['dependency' => $dependency])) {
// ... здесь создаём содержимое ...
// ... тут створюємо зміст ...
$this->endCache();
}
```
### Вариации <a name="variations"></a>
### Варіації <a name="variations"></a>
Кэшируемое содержимое может быть изменено в соответствии с некоторыми параметрами. Например, для веб-приложений, поддерживающих несколько языков, одна и та же часть кода может создавать содержимое на нескольких языках. Поэтому у вас может возникнуть желание кэшировать содержимое в зависимости от текущего языка приложения.
Вміст, що кешується, може бути змінено відповідно до деяких параметрів.
Наприклад, для веб-додатка із підтримкою декількох мов, один і той же шматок представлення коду може генерувати контент на різних мовах.
Таким чином, ви можете змінювати кешований вміст відповідно до поточної мови додатка.
Чтобы задать вариации кэша, установите параметр [[yii\widgets\FragmentCache::variations|variations]], который должен быть массивом, содержащим скалярные значения, каждое из которых представляет определенный коэффициент вариации. Например,
чтобы кэшировать содержимое в зависимости от языка приложения, вы можете использовать следующий код:
Щоб вказати варіації кешу, встановіть опцію [[yii\widgets\FragmentCache::variations|variations]],
яка повинна бути масивом скалярних значень, кожне з яких представляє певний коефіцієнт варіації.
Наприклад, щоб кешувати вміст у залежності від мови додатка, ви можете використовувати наступний код:
```php
if ($this->beginCache($id, ['variations' => [Yii::$app->language]])) {
// ... здесь создаём содержимое ...
// ... тут створюємо зміст ...
$this->endCache();
}
```
### Переключение кэширования <a name="toggling-caching"></a>
### Перемикання кешування <a name="toggling-caching"></a>
Иногда может потребоваться включать кеширование фрагментов только для определённых условий. Например, страницу с формой мы хотим кэшировать только тогда, когда обращение к ней произошло впервые (посредством GET запроса). Любое последующее отображение формы (посредством POST запроса) не должно быть кэшировано, потому что может содержать данные, введённые пользователем. Для этого мы задаём параметр [[yii\widgets\FragmentCache::enabled|enabled]]:
Іноді, ви можете захотіти увімкнути кешування фрагмента тільки за певних умов. Наприклад, для сторінки, яка відображає форму,
ви хочете кешувати тільки форму при її початковому запиті (через GET-запит). Будь-яке подальше відображення (через POST-запит)
форми не повинне кешуватися, тому що форма може містити дані, що ввів користувач.
Щоб зробити це, ви можете встановити опцію [[yii\widgets\FragmentCache::enabled|enabled]] наступним чином:
```php
if ($this->beginCache($id, ['enabled' => Yii::$app->request->isGet])) {
// ... здесь создаём содержимое ...
// ... тут створюємо зміст ...
$this->endCache();
}
```
## Вложенное кэширование <a name="nested-caching"></a>
## Вкладене кешування <a name="nested-caching"></a>
Кэширование фрагментов может быть вложенным. Это значит, что кэшируемый фрагмент окружён более крупным фрагментом (содержится в нём), который также кэшируется. Например, комментарии кэшируются во внутреннем фрагменте кэша, и они же кэшируются вместе с содержимым сообщения во внешнем фрагменте кэша. Следующий код демонстрирует как два фрагмента кэша могут быть вложенными:
Кешування фрагментів може бути вкладеним. Тобто, кешований фрагмент може бути укладений в інший фрагмент, що також кешується.
Наприклад, коментарі кешируются у внутрішньому фрагменті кешу, і вони ж кешуються разом із вмістом поста у зовнішньому
фрагменті кеша. Наступний код показує, як два кеша фрагментів можуть бути вкладеними:
```php
if ($this->beginCache($id1)) {
// ...логика создания контента...
// ...логіка створення контента...
if ($this->beginCache($id2, $options2)) {
// ...логика создания контента...
// ...логіка створення контента...
$this->endCache();
}
// ...логика создания контента...
// ...логіка створення контента...
$this->endCache();
}
```
Параметры кэширования могут быть различными для вложенных кэшей. Например, внутренний и внешний кэши в вышеприведённом примере могут иметь разные сроки хранения. Даже когда данные внешнего кэша уже не являются актуальными, внутренний кеш может содержать актуальный фрагмент. Тем не менее, обратное не верно. Если внешний кэш актуален, данные будут отдаваться из него даже если внутренний кэш содержит устаревшие данные. Следует проявлять осторожность при выставлении срока хранения и задания зависимостей для вложенных кэшей. В противном случае вы можете получить устаревшие данные.
Для вкладених кешів можут бути встановлені різні опції кешування. Наприклад, внутрішні кеші і зовнішні кеші можуть використовувати
різні значення тривалості кеша. Навіть коли дані зовнішнього кеша вже є недійсними, внутрішній кеш все ще може містити актуальний фрагмент.
Тим не менш, це не є вірним у зворотньому напрямку. Якщо зовнішній кеш є дійсним, то він буде продовжувати віддавати кешовану копію,
навіть якщо внутрішній кеш є недійсним. Таким чином, ви повинні бути обережні у визначенні тривалості або залежностей вкладених кешей,
в іншому випадку застарілі внутрішні фрагменти можуть зберігатися в зовнішньому фрагменті.
## Динамическое содержимое <a name="dynamic-content"></a>
## Динамічний зміст <a name="dynamic-content"></a>
Когда используется кэширование фрагментов, вы можете столкнуться с ситуацией когда большой фрагмент содержимого статичен за исключением одного или нескольких мест. Например, заголовок страницы может отображаться в главном меню вместе с
именем текущего пользователя. Еще одна проблема в том, что содержимое, которое было закэшировано, может содержать PHP код, который должен выполняться для каждого запроса (например код для регистрации в asset bundle). Обе проблемы могут быть решены с помощью, так называемой функции *динамического содержимого*.
При використанні кешування фрагментів, ви можете зіткнутися із ситуацією, коли великий фрагмент змісту є відносно статичним,
за винятком одного або декількох місць. Наприклад, заголовок сторінки може відображатися у головному меню разом
з імʼям поточного користувача. Інша проблема в тому, що закешований зміст може містити код PHP, який повинен
виконуватися при кожному запиті (наприклад, код для реєстрації пакету ресурсів). Обидві ці проблеми можуть бути
вирішені за допомогою так званої функції *динамічного змісту*.
Динамическое содержимое значит, что часть вывода не будет закэширована даже если она заключена в кэширование фрагментов. Чтобы сделать содержимое динамическим постоянно, оно должно быть создано, используя специальный PHP код.
Динамічний зміст означає фрагмент виведення, який не повинен кешуватися, навіть якщо він укладений у кешування фрагментів.
Для того, щоб зробити зміст динамічним постійно, він повинен бути створений за допомогою деякого PHP коду для кожного запиту,
навіть якщо зміст віддаєтся із кеша.
Вы можете вызвать [[yii\base\View::renderDynamic()]] в пределах кэширования фрагмента для вставки динамического содержимого
в нужное место, как в примере ниже:
Ви можете викликати [[yii\base\View::renderDynamic()]] в кеші фрагмента для вставки динамічного контенту у потрібне місце,
як у прикладі нижче:
```php
if ($this->beginCache($id1)) {
// ...логика создания контента...
// ...логіка створення контента...
echo $this->renderDynamic('return Yii::$app->user->identity->name;');
// ...логика создания контента...
// ...логіка створення контента...
$this->endCache();
}
```
Метод [[yii\base\View::renderDynamic()|renderDynamic()]] принимает некоторую часть PHP кода как параметр.
Возвращаемое значение этого кода будет вставлено в динамическое содержимое. Этот PHP код будет выполняться для каждого запроса, независимо от того находится ли он внутри кэширования фрагмента или нет.
Метод [[yii\base\View::renderDynamic()|renderDynamic()]] бере деяку частину коду PHP в якості параметра.
Значення, що повертається від коду PHP, трактується як динамічний зміст. Цей код PHP буде виконуватися при кожному запиті,
незалежно від того, чи віддається фрагмент із кешу або ні.
Псевдоніми
=========
==========
Псевдоніми використовуються для позначення шляхів до файлів або URL адрес і допомагають уникнути використання абсолютних шляхів
або URL в коді. Для того, щоб не переплутати псевдонім із звичайним шляхом до файлу або URL, він повинен починатися з `@`. В Yii
є безліч заздалегідь визначених псевдонімів. Наприклад, `@yii` вказує на директорію, в яку був встановлений
є багато заздалегідь визначених псевдонімів. Наприклад, `@yii` вказує на директорію, в яку був встановлений
Yii framework, а `@web` можна використовувати для отримання базового URL поточного додатку.
Створення псевдонімів <a name="defining-aliases"></a>
----------------------------------------------
---------------------
Для створення псевдоніма шляху до файлу або URL використовується метод [[Yii::setAlias()]]:
......@@ -20,12 +20,14 @@ Yii::setAlias('@foo', '/path/to/foo');
Yii::setAlias('@bar', 'http://www.example.com');
```
> Примітка: псевдонім шляху до файлу або URL *не* обов'язково вказує на існуючий файл або ресурс.
> Примітка: псевдонім шляху до файлу або URL *не* обовʼязково вказує на існуючий файл або ресурс.
Використовуючи вже заданий псевдонім, ви можете отримати на основі нього новий без виклику [[Yii :: setAlias ​​()]]. Зробити це можна, додавши в його кінець `/`, за яким слід один або більше сегментів шляху. Псевдоніми, визначені за допомогою
[[Yii::setAlias()]], є *кореневими псевдонімами*, в той час як отримані з них називаються похідними псевдонімами. На приклад, `@foo` є кореневим псевдонімом, а `@foo/bar/file.php` — похідним.
Використовуючи вже заданий псевдонім, ви можете отримати на основі нього новий (без виклику [[Yii::setAlias()]]),
додавши в його кінець `/`, за яким слідує один або більше сегментів шляху. Псевдоніми, визначені за допомогою
[[Yii::setAlias()]], є *кореневими псевдонімами*, в той час як отримані з них називаються *похідними псевдонімами*.
На приклад, `@foo` є кореневим псевдонімом, а `@foo/bar/file.php` — похідним.
Ви можете задати новий псевдонім, використовуючи раніше створений псевдонім (не важливо, кореневої він чи похідний):
Ви можете задати новий псевдонім, використовуючи раніше створений псевдонім (не важливо, кореневий він чи похідний):
```php
Yii::setAlias('@foobar', '@foo/bar');
......@@ -48,9 +50,10 @@ return [
Перетворення псевдонімів <a name="resolving-aliases"></a>
----------------------------------------------------
------------------------
Метод [[Yii :: getAlias ​​()]] перетворює кореневої псевдонім в шлях до файлу або URL, який цей псевдонім представляє. Цей же метод може працювати і з похідними псевдонімами:
Виклик [[Yii::getAlias()]] перетворює кореневий псевдонім в шлях до файлу або URL, який цей псевдонім представляє.
Цей же метод може працювати і з похідними псевдонімами:
```php
echo Yii::getAlias('@foo'); // виведе: /path/to/foo
......@@ -58,11 +61,13 @@ echo Yii::getAlias('@bar'); // виведе: http://www.example.co
echo Yii::getAlias('@foo/bar/file.php'); // виведе: /path/to/foo/bar/file.php
```
Шлях або URL, представлений похідним псевдонімом, визначається шляхом заміни в ньому частині, що відповідає кореневого псевдоніму, на відповідний йому шлях або URL.
Шлях або URL, представлений похідним псевдонімом, визначається шляхом заміни в ньому частині, що відповідає кореневого псевдоніму,
на відповідний йому шлях або URL.
> Примітка: Метод [[Yii :: getAlias ​​()]] не перевіряє фактичного існування одержуваного шляху або URL.
> Примітка: Метод [[Yii::getAlias()]] не перевіряє фактичного існування одержуваного шляху або URL.
Кореневої псевдонім може містити знаки '/'. При цьому метод [[Yii::getAlias()]] коректно визначить, яка частина псевдоніма є кореневої і вірно сформує шлях або URL:
Кореневий псевдонім може містити знаки `/`. При цьому метод [[Yii::getAlias()]] коректно визначить, яка частина
псевдоніма є кореневої і вірно сформує шлях або URL:
```php
Yii::setAlias('@foo', '/path/to/foo');
......@@ -73,10 +78,13 @@ Yii::getAlias('@foo/bar/file.php'); // виведе: /path2/bar/file.php
Якби `@foo/bar` не був оголошений кореневим псевдонімом, остання строка вивела б `/path/to/foo/bar/file.php`.
Використання псевдонімів. <a name="using-aliases"></a>
------------------------------------------------
Псевдоніми розпізнаються в багатьох частинах Yii без необхідності попередньо викликати [[Yii::getAlias()]] для отримання шляху або URL. Наприклад, [[yii\caching\FileCache::cachePath]] приймає як звичайний шлях до файлу, так і псевдонім шляху завдяки префіксу `@`, який дозволяє їх розрізняти.
Використання псевдонімів <a name="using-aliases"></a>
------------------------
Псевдоніми розпізнаються в багатьох частинах Yii без необхідності попереднього виклику [[Yii::getAlias()]]
для отримання шляху або URL. Наприклад, [[yii\caching\FileCache::cachePath]] приймає як звичайний шлях до файлу,
так і псевдонім шляху завдяки префіксу `@`, який дозволяє їх розрізняти.
```php
use yii\caching\FileCache;
......@@ -90,28 +98,31 @@ $cache = new FileCache([
Заздалегідь визначені псевдоніми <a name="predefined-aliases"></a>
----------------------------------------------------------
--------------------------------
В Yii заздалегідь визначені псевдоніми для часто використовуваних шляхів до файлів і URL:
- `@yii`: директорія, в якій знаходиться файл `BaseYii.php` (директорія фреймворка).
- `@app`: [[yii\base\Application::basePath|базовий шлях]] поточного додатку.
- `@runtime`: [[yii\base\Application::runtimePath|директорія runtime]] поточного додатку.
- `@vendor`: [[yii\base\Application::vendorPath|директорія vendor Composer].
- `@webroot`: вебрут поточного веб додатка (там де `index.php`).
- `@web`: базовий URL поточного додатку.
- `@runtime`: [[yii\base\Application::runtimePath|директорія runtime]] поточного додатку. За замовчуванням `@app/runtime`.
- `@webroot`, коренева веб-директорія поточного веб-додатку. Визначається на основі директорії розташування вхідного скрипта.
- `@web`, базовий URL поточного додатку. Має таке ж значення, як і [[yii\web\Request::baseUrl]].
- `@vendor`, [[yii\base\Application::vendorPath|директорія vendor Composer]]. За замовчуванням `@app/vendor`.
- `@bower`, директорія, що містить [пакети bower](http://bower.io/). За замовчуванням `@vendor/bower`.
- `@npm`, директорія, що містить [пакети npm](https://www.npmjs.org/). За замовчуванням `@vendor/npm`.
Псевдонім `@yii` задається в момент підключення файлу `Yii.php` у [вхідному скрипті](structure-entry-scripts.md).
Решта псевдоніми задаються в конструкторі додатки в момент застосування [конфигурації](concept-configurations.md).
Решта псевдонімів задаються в конструкторі додатка в момент застосування [конфигурації](concept-configurations.md).
Псевдоніми розширень <a name="extension-aliases"></a>
------------------------------------------------
--------------------
Для кожного [розширення](structure-extensions.md), встановлюваного через Composer, автоматично задається псевдонім.
Його ім'я відповідає кореневого простору імен розширення відповідно до його `composer.json`. Псевдонім представляє
шлях до кореневої директорії пакета. Наприклад, якщо ви встановите розширення `yiisoft/yii2-jui`, то вам автоматично стане доступний псевдонім `@yii/jui`. Він створюється на етапі [первинного завантаження (bootstrapping)](runtime-bootstrapping.md)
приблизно так:
Для кожного [розширення](structure-extensions.md), що встановлюється через Composer, автоматично задається псевдонім.
Його імʼя відповідає кореневому простору імен розширення відповідно до його `composer.json`, і кожен псевдонім представляє
шлях до кореневої директорії пакета. Наприклад, якщо ви встановите розширення `yiisoft/yii2-jui`,
то вам автоматично стане доступним псевдонім `@yii/jui`, який будет створено на етапі
[первинного завантаження (bootstrapping)](runtime-bootstrapping.md) наступним чином:
```php
Yii::setAlias('@yii/jui', 'VendorPath/yiisoft/yii2-jui');
......
Автозавантаження класів
=================
=======================
Пошук і підключення файлів класів в Yii реалізовано за допомогою
[автозавантаження класів](http://www.php.net/manual/ru/language.oop5.autoload.php). Фреймворк надає свій швидкий сумісний з [PSR-4](https://github.com/php-fig/fig-standards/blob/master/proposed/psr-4-autoloader/psr-4-autoloader.md)
автозавантажувач, який встановлюється в момент підключення `Yii.php`.
[автозавантаження класів](http://www.php.net/manual/ru/language.oop5.autoload.php).
Фреймворк надає власний швидкісний автозавантажувач, що сумісний з
[PSR-4](https://github.com/php-fig/fig-standards/blob/master/proposed/psr-4-autoloader/psr-4-autoloader.md),
який встановлюється в момент підключення файлу `Yii.php`.
> Примітка: Для простоти опису, в цьому розділі ми будемо говорити тільки про автозавантаження класів.
Тим не менш, все описане також стосується до інтерфейсів і трейтів.
> Примітка: Для простоти оповіді, в цьому розділі ми будемо говорити тільки про автозавантаження класів. Тим не менш, все описане може бути застосовно до інтерфейсів і трейтів.
Як використовувати автозавантажувач Yii <a name="using-yii-autoloader"></a>
--------------------------------------------------------------
Використання автозавантажувача Yii <a name="using-yii-autoloader"></a>
----------------------------------
При використанні автозавантажувача класів Yii слід дотримуватися два простих правила створення і іменування класів:
Для використання автозавантажувача класів Yii слід дотримуватися два простих правила створення і іменування класів:
* Кожен клас повинен належати простору імен (тобто `foo\bar\MyClass`).
* Кожен клас повинен належати простору імен (тобто `foo\bar\MyClass`)
* Кожен клас повинен знаходитися в окремому файлі, шлях до якого визначаться наступним правилом:
```php
// $className — це абсолютне ім'я класу, що починається з "\"
// $className — це абсолютне імʼя класу, що починається з "\"
$classFile = Yii::getAlias('@' . str_replace('\\', '/', $className) . '.php');
```
Наприклад, якщо абсолютне ім'я класу `foo\bar\MyClass`, то [псевдонім шляху](concept-aliases.md) даного файлу буде
`@foo/bar/MyClass.php`. Для того, щоб даний псевдонім можна було перетворити в шлях до файлу, необхідно щоб або `@foo` або `@foo/bar` був [кореневим псевдонімом](concept-aliases.md#defining-aliases).
Наприклад, якщо абсолютне імʼя класу `foo\bar\MyClass`, то [псевдонім шляху](concept-aliases.md) даного файлу класу буде
`@foo/bar/MyClass.php`. Для того, щоб даний псевдонім можна було перетворити в шлях до файлу, необхідно щоб або `@foo`
або `@foo/bar` був [кореневим псевдонімом](concept-aliases.md#defining-aliases).
при використанні [шаблону додатку basic](start-installation.md) ви можете зберігати свої класи в просторі імен `app`.
В цьому випадку вони будуть завантажуватися автоматично без створення нового псевдоніма. Це працює тому як `@app`
є [заздалегідь певним псевдонімом](concept-aliases.md#predefined-aliases) і таке ім'я класу як
`app\components\MyClass` відповідно до описаного вище алготімом перетвориться в шлях
`директорияПриложения/components/MyClass.php`.
При використанні [базового шаблону додатка](start-installation.md) ви можете зберігати свої класи в просторі імен
верхнього рівня `app`, щоб вони могли бути автоматично завантажені Yii без створення нового псевдоніма.
Це працює, тому як `@app` є [заздалегідь визначеним псевдонімом](concept-aliases.md#predefined-aliases) і таке імʼя класу,
як `app\components\MyClass` відповідно до описаного вище алготімом перетвориться в шлях `AppBasePath/components/MyClass.php`.
В [шаблоні додатку advanced](tutorial-advanced-app.md) кожен рівень додатку володіє власним кореневим псевдонімом. Наприклад, для frontend кореневим псевдонімом є `@frontend`, а для backend — `@backend`. Це дозволяє
розмістити класи frontend в простір імен `frontend`, а класи backend в простір імен `backend`. При цьому класи будуть завантажені автоматично.
У [розширеному шаблоні додатка](tutorial-advanced-app.md) кожен рівень додатку володіє власним кореневим псевдонімом.
Наприклад, для frontend кореневим псевдонімом є `@frontend`, а для backend — `@backend`. Це дозволяє розмістити класи
frontend в простір імен `frontend`, а класи backend в простір імен `backend`. При цьому класи будуть завантажені автоматично.
Карта класів <a name="class-map"></a>
---------------------------------
Мапа класів <a name="class-map"></a>
-----------
Автозавантажувач Yii підтримує *карту класів*. Ця можливість дозволяє вказати шлях до файлу для кожного імені класу.
При завантаженні класу автозавантажувач перевіряє наявність класу в карті. Якщо він там є, відповідний файл буде завантажений
Автозавантажувач Yii підтримує *мапу класів*. Ця можливість дозволяє вказати шлях до файлу для кожного імені класу.
При завантаженні класу автозавантажувач перевіряє наявність класу в мапі. Якщо він там є, відповідний файл буде завантажений
безпосередньо без будь-яких додаткових перевірок. Це робить автозагрузку дуже швидкою. Всі класи самого фреймворка
завантажуються саме цим способом.
Ви маєте можливість додати клас в карту `Yii::$classMap` наступним чином:
Ви маєте можливість додати клас в мапу `Yii::$classMap` наступним чином:
```php
Yii::$classMap['foo\bar\MyClass'] = 'path/to/MyClass.php';
```
Для вказівки шляхів до файлів класів можна використовувати [псевдоніми](concept-aliases.md). Карту класів необхідно сформувати в процесі [первинного завантаження](runtime-bootstrapping.md) так як вона повинна бути готова до використання класів.
Для вказівки шляхів до файлів класів можна використовувати [псевдоніми](concept-aliases.md). Мапу класів необхідно сформувати
в процесі [первинного завантаження](runtime-bootstrapping.md), так як вона повинна бути сформована до використання класів.
Використання інших автозавантажувачів <a name="using-other-autoloaders"></a>
------------------------------------------------------------------
-------------------------------------
Так як Yii використовує Composer в якості менеджера залежностей, рекомендується додатково встановити його автозавантажувач.
Якщо ви використовуєте які-небудь сторонні бібліотеки, в яких є свої Автозавантажувач, ці Автозавантажувач також необхідно
Оскільки Yii використовує Composer у якості менеджера залежностей, рекомендується додатково встановити його автозавантажувач.
Якщо ви використовуєте які-небудь сторонні бібліотеки із власними автозавантажувачами, то ці автозавантажувачі також необхідно
встановити.
При використанні додаткових автозавантажувач файл `Yii.php` повинен бути підключений *після* їх установки. це дозволить
автозавантажувачу Yii першим пробувати завантажити клас. Приміром, наведений нижче код взятий з
[вхідного скрипта](structure-entry-scripts.md) [шаблону додатку basic](start-installation.md). Перший рядок встановлює автозавантажувач Composer, а друга - автозавантажувач Yii:
При використанні додаткових автозавантажувачів, файл `Yii.php` повинен бути підключений *після* їх установки.
Це дозволить автозавантажувачу Yii першим намагатися завантажити клас. Наприклад, наведений нижче код взятий з
[вхідного скрипта](structure-entry-scripts.md) [базового шаблону додатка](start-installation.md).
Перший рядок встановлює автозавантажувач Composer, а другий - автозавантажувач Yii:
```php
require(__DIR__ . '/../vendor/autoload.php');
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
```
Ви можете використовувати автозавантажувач Composer без автозавантажувачa Yii. Однак, швидкість автозавантаження в цьому випадку може зменшиться. Також вам буде необхідно слідувати правилам автозавантажувача Composer.
Ви можете використовувати автозавантажувач Composer без автозавантажувачa Yii, однак, швидкість автозавантаження в
цьому випадку може зменшиться. До того ж вам буде необхідно слідувати правилам автозавантажувача Composer.
> Інформація: Якщо ви не хочете використовувати автозавантажувач Yii, створіть свою версію файлу `Yii.php`
і підключіть його в [вхідному скрипті](structure-entry-scripts.md).
і підключіть його у [вхідному скрипті](structure-entry-scripts.md).
Автозавантаження класів розширень <a name="autoloading-extension-classes"></a>
-------------------------------------------------------------------
---------------------------------
Автозавантажувач Yii може автоматично завантажувати класи [розширень](structure-extensions.md) в тому випадку, якщо дотримується єдине правило. Розширення повинно правильно описати розділ 'autoload' у файлі 'composer.json'. Більш докладно про це можна дізнатися з [офіційній документації Composer](https://getcomposer.org/doc/04-schema.md#autoload).
Автозавантажувач Yii може автоматично завантажувати класи [розширень](structure-extensions.md), при умові виконання вимоги
коректного визначення секції `autoload` у файлі `composer.json`. Більш докладно про це можна дізнатися з
[офіційної документації Composer](https://getcomposer.org/doc/04-schema.md#autoload).
Якщо ви не використовуєте автозавантажувач Yii, то класи розширень можуть бути автоматично завантажені з допомогою автозавантажувач Composer.
<?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="35.0" width="100.0" x="872.1807999999999" y="-14.764159999999947"/>
<y:Fill color="#FFCC99" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="32.265625" modelName="custom" textColor="#000000" visible="true" width="69.712890625" x="15.1435546875" y="1.3671875">компонент
додатка<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="35.0" width="100.0" x="702.4223999999999" y="-91.97375999999994"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="70.28125" x="14.859375" y="8.43359375">вхідний скрипт<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:ShapeNode>
<y:Geometry height="35.0" width="100.0" x="702.4223999999999" y="-14.764159999999947"/>
<y:Fill color="#FF9900" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="68.21875" x="15.890625" y="8.43359375">додаток<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="n3">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="35.0" width="100.0" x="702.4223999999999" y="62.44544000000004"/>
<y:Fill color="#FF9900" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="60.267578125" x="19.8662109375" y="8.433593750000007">контролер<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="n4">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="35.0" width="100.0" x="872.1807999999999" y="62.44544000000005"/>
<y:Fill color="#FFCC99" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="31.43359375" x="34.283203125" y="8.43359375">фільтр<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="35.0" width="100.0" x="532.664" y="23.901600000000087"/>
<y:Fill color="#FF9900" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="47.728515625" x="26.1357421875" y="8.43359375">модуль<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="35.0" width="100.0" x="618.4047999999991" y="139.65504000000004"/>
<y:Fill color="#99CC00" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="29.611328125" x="35.1943359375" y="8.43359375">представлення<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="35.0" width="100.0" x="786.161599999999" y="139.65504000000004"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="40.28125" x="29.859375" y="8.43359375">модель<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="n8">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="35.0" width="100.0" x="532.664" y="216.86464000000004"/>
<y:Fill color="#99CC00" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="42.923828125" x="28.5380859375" y="8.43359375">віджет<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="n9">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="35.0" width="100.0" x="702.4223999999999" y="216.86464000000004"/>
<y:Fill color="#99CC00" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" textColor="#000000" visible="true" width="77.986328125" x="11.0068359375" y="8.43359375">asset bundle<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="n2" 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="diamond"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="22.97265625" x="2.5392475585936154" y="-25.635106635436955">1:1<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="14.025600000000054" distanceToCenter="true" position="right" ratio="0.17992697197425173" segment="-1"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e1" source="n0" 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="diamond"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="24.96484375" x="-48.97602119140629" y="-23.09200633216852">0..*<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="14.025599999999994" distanceToCenter="true" position="right" ratio="0.5470891790487767" segment="-1"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e2" source="n5" 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="diamond"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="24.96484375" x="15.193962466822086" y="30.674065521861735">0..*<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="44.894496863129426" distanceToCenter="true" position="right" ratio="0.25416574623968574" segment="-1"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e3" source="n3" 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="diamond"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="24.96484375" x="2.7719538085937074" y="-26.04470613037104">1..*<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="15.254400000000032" distanceToCenter="true" position="right" ratio="0.2090245199765919" segment="-1"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e4" source="n3" 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="diamond"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="24.96484375" x="-57.39355288912964" y="-63.846685518352906">0..*<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="43.47658308018222" distanceToCenter="true" position="right" ratio="0.881412889692355" segment="-1"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e5" source="n5" target="n5">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="582.664" y="-3.598399999999913"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="diamond"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="24.96484375" x="-17.888505566406252" y="-42.41848039245597">0..*<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="16.483200000000004" distanceToCenter="true" position="right" ratio="5.822600000000001" segment="-2"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e6" source="n6" 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="diamond"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="24.96484375" x="-12.223966589163297" y="-24.76668258085064">0..*<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="11.385360101663515" distanceToCenter="true" position="left" ratio="0.10670293331985262" segment="-1"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e7" source="n7" 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="diamond"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="24.96484375" x="-9.313146217848043" y="-26.098020948340803">0..*<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="14.669798038586146" distanceToCenter="true" position="right" ratio="0.1670192242704811" segment="-1"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e8" source="n9" target="n6">
<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="diamond"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="24.96484375" x="-9.797233483694527" y="-25.82443358614151">0..*<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="14.15599378957306" distanceToCenter="true" position="right" ratio="0.15481212573620068" segment="-1"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e9" source="n8" target="n6">
<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="diamond"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="24.96484375" x="-15.633139430038" y="-24.050683308790553">0..*<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="13.24330808446041" distanceToCenter="true" position="left" ratio="0.05506723556297327" segment="-1"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e10" source="n4" 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="diamond"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="24.96484375" x="-47.337621191406356" y="-22.682408449706998">0..*<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="13.616000000000007" distanceToCenter="true" position="right" ratio="0.5" segment="0"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e11" source="n9" target="n8">
<data key="d9"/>
<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="diamond"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="24.96484375" x="-44.265598339843905" y="-19.61040553222648">0..*<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="10.543999999999983" distanceToCenter="true" position="right" ratio="0.4117077892835431" segment="-1"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e12" source="n7" target="n6">
<data key="d9"/>
<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="diamond"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.1328125" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="24.96484375" x="-44.81721357421975" y="-19.610410805664003">0..*<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="10.543999999999983" distanceToCenter="true" position="right" ratio="0.4531592446547025" segment="-1"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
</graph>
<data key="d0">
<y:Resources/>
</data>
</graphml>
<?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:SVGNode>
<y:Geometry height="70.13700103759766" width="56.558998107910156" x="198.38633947503078" y="261.099458694458"/>
<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" hasText="false" height="4.0" modelName="custom" textColor="#000000" visible="true" width="4.0" x="26.279499053955078" y="74.13700103759766">
<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="4.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<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="27.34375" x="-31.34375" y="25.717914581298828">користувач<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.5" labelRatioY="0.0" nodeRatioX="-0.5" nodeRatioY="0.0" offsetX="-4.0" offsetY="0.0" 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="n1">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="45.0" width="119.0" x="789.0653619766235" y="637.1271178722382"/>
<y:Fill color="#99CCFF" transparent="false"/>
<y:BorderStyle hasColor="false" 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="41.158203125" y="13.1494140625">модель<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="46.887996673583984" width="39.527000427246094" x="828.8018617630005" y="544.9831195354463"/>
<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="53.376953125" x="-6.924976348876953" y="-30.723247528076172">база даних<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="-12.022075653076172" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" hasText="false" height="4.0" modelName="custom" textColor="#000000" visible="true" width="4.0" x="17.763500213623047" y="21.443998336791992">
<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:SVGNodeProperties usingVisualBounds="true"/>
<y:SVGModel svgBoundsPolicy="0">
<y:SVGContent refid="2"/>
</y:SVGModel>
</y:SVGNode>
</data>
</node>
<node id="n3">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="45.0" width="119.0" x="789.0653619766235" y="713.6271178722382"/>
<y:Fill color="#99CC00" transparent="false"/>
<y:BorderStyle hasColor="false" 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="28.005859375" x="45.4970703125" y="13.1494140625">представлення<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="n4" yfiles.foldertype="group">
<data key="d4"/>
<data key="d6">
<y:ProxyAutoBoundsNode>
<y:Realizers active="0">
<y:GroupNode>
<y:Geometry height="377.0372841596604" width="219.27949905395508" x="527.4919853210449" y="407.9266515731811"/>
<y:Fill color="#FFEFD6" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="node_width" backgroundColor="#FF9900" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="22.37646484375" modelName="internal" modelPosition="t" textColor="#000000" visible="true" width="219.27949905395508" x="0.0" y="0.0">контролер</y:NodeLabel>
<y:Shape type="rectangle"/>
<y:State closed="false" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
<y:Insets bottom="15" bottomF="15.0" left="15" leftF="15.0" right="15" rightF="15.0" top="15" topF="15.0"/>
<y:BorderInsets bottom="0" bottomF="0.0" left="2" leftF="1.7335329055786133" right="0" rightF="0.0" top="0" topF="0.0"/>
</y:GroupNode>
<y:GroupNode>
<y:Geometry height="50.0" width="50.0" x="313.2978515625" y="412.2765645980835"/>
<y:Fill color="#F5F5F5" transparent="false"/>
<y:BorderStyle color="#000000" type="dashed" width="1.0"/>
<y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="22.37646484375" modelName="internal" modelPosition="t" textColor="#000000" visible="true" width="59.02685546875" x="-4.513427734375" y="0.0">Folder 1</y:NodeLabel>
<y:Shape type="roundrectangle"/>
<y:State closed="true" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
<y:Insets bottom="5" bottomF="5.0" left="5" leftF="5.0" right="5" rightF="5.0" top="5" topF="5.0"/>
<y:BorderInsets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/>
</y:GroupNode>
</y:Realizers>
</y:ProxyAutoBoundsNode>
</data>
<graph edgedefault="directed" id="n4:">
<node id="n4::n0">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="150.55899810791016" x="563.2124862670898" y="445.3031164169311"/>
<y:Fill color="#FFFFFF" 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="72.70703125" x="38.92598342895508" y="5.6494140625">створення дії<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="rectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n4::n1">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="45.0" width="159.91864204406738" x="558.5326642990112" y="521.8166599273682"/>
<y:Fill color="#FFFFFF" 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="77.34765625" x="41.28549289703369" y="13.1494140625">накладання
фільтрів<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="diamond"/>
</y:ShapeNode>
</data>
</node>
<node id="n4::n2" yfiles.foldertype="group">
<data key="d4"/>
<data key="d6">
<y:ProxyAutoBoundsNode>
<y:Realizers active="0">
<y:GroupNode>
<y:Geometry height="162.71328270435333" width="187.54596614837646" x="544.2255182266235" y="607.2506530284882"/>
<y:Fill color="#99336635" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="node_width" backgroundColor="#993366" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="22.37646484375" modelName="internal" modelPosition="t" textColor="#FFFFFF" visible="true" width="187.54596614837646" x="0.0" y="0.0">дія</y:NodeLabel>
<y:Shape type="rectangle"/>
<y:State closed="false" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
<y:Insets bottom="15" bottomF="15.0" left="15" leftF="15.0" right="15" rightF="15.0" top="15" topF="15.0"/>
<y:BorderInsets bottom="4" bottomF="3.8368178606033325" left="4" leftF="3.9869680404663086" right="3" rightF="3.0" top="0" topF="0.0"/>
</y:GroupNode>
<y:GroupNode>
<y:Geometry height="50.0" width="50.0" x="0.0" y="60.0"/>
<y:Fill color="#F5F5F5" transparent="false"/>
<y:BorderStyle color="#000000" type="dashed" width="1.0"/>
<y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="22.37646484375" modelName="internal" modelPosition="t" textColor="#000000" visible="true" width="59.02685546875" x="-4.513427734375" y="0.0">Folder 3</y:NodeLabel>
<y:Shape type="roundrectangle"/>
<y:State closed="true" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
<y:Insets bottom="5" bottomF="5.0" left="5" leftF="5.0" right="5" rightF="5.0" top="5" topF="5.0"/>
<y:BorderInsets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/>
</y:GroupNode>
</y:Realizers>
</y:ProxyAutoBoundsNode>
</data>
<graph edgedefault="directed" id="n4::n2:">
<node id="n4::n2::n0">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="150.55899810791016" x="563.2124862670898" y="644.6271178722382"/>
<y:Fill color="#FFFFFF" 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.705078125" x="43.92695999145508" y="5.6494140625">завантаження моделі<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="rectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n4::n2::n1">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="150.55899810791016" x="563.2124862670898" y="721.1271178722382"/>
<y:Fill color="#FFFFFF" 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="66.02734375" x="42.26582717895508" y="5.6494140625">відображення
представлення<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="rectangle"/>
</y:ShapeNode>
</data>
</node>
</graph>
</node>
</graph>
</node>
<node id="n5">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="45.0" width="119.0" x="198.3863394750308" y="713.6271178722382"/>
<y:Fill color="#FFCC99" transparent="false"/>
<y:BorderStyle hasColor="false" 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="116.072265625" x="1.4638671875000284" y="13.1494140625">компонент
відповіді<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="45.0" width="119.0" x="789.0653619766235" y="254.50096702575684"/>
<y:Fill color="#FFCC99" transparent="false"/>
<y:BorderStyle hasColor="false" 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="106.732421875" x="6.1337890625" y="13.1494140625">компонент
запиту<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" yfiles.foldertype="group">
<data key="d4"/>
<data key="d6">
<y:ProxyAutoBoundsNode>
<y:Realizers active="0">
<y:GroupNode>
<y:Geometry height="144.132230758667" width="219.27949905395508" x="527.4919853210449" y="222.86873626708984"/>
<y:Fill color="#FFEFD6" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="node_width" backgroundColor="#FF9900" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="22.37646484375" modelName="internal" modelPosition="t" textColor="#000000" visible="true" width="219.27949905395508" x="0.0" y="0.0">додаток</y:NodeLabel>
<y:Shape type="rectangle"/>
<y:State closed="false" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
<y:Insets bottom="15" bottomF="15.0" left="15" leftF="15.0" right="15" rightF="15.0" top="15" topF="15.0"/>
<y:BorderInsets bottom="0" bottomF="0.0" left="21" leftF="20.720500946044922" right="18" rightF="18.0" top="2" topF="1.7557659149169922"/>
</y:GroupNode>
<y:GroupNode>
<y:Geometry height="50.0" width="50.0" x="0.0" y="60.0"/>
<y:Fill color="#F5F5F5" transparent="false"/>
<y:BorderStyle color="#000000" type="dashed" width="1.0"/>
<y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="22.37646484375" modelName="internal" modelPosition="t" textColor="#000000" visible="true" width="59.02685546875" x="-4.513427734375" y="0.0">Folder 2</y:NodeLabel>
<y:Shape type="roundrectangle"/>
<y:State closed="true" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
<y:Insets bottom="5" bottomF="5.0" left="5" leftF="5.0" right="5" rightF="5.0" top="5" topF="5.0"/>
<y:BorderInsets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/>
</y:GroupNode>
</y:Realizers>
</y:ProxyAutoBoundsNode>
</data>
<graph edgedefault="directed" id="n7:">
<node id="n7::n0">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="150.55899810791016" x="563.2124862670898" y="262.00096702575684"/>
<y:Fill color="#FFFFFF" 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="73.369140625" x="38.59492874145508" y="5.6494140625">визначення маршруту<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="rectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n7::n1">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="150.55899810791016" x="563.2124862670898" y="322.00096702575684"/>
<y:Fill color="#FFFFFF" 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="90.0390625" x="30.259967803955078" y="5.6494140625">створення контролера<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="rectangle"/>
</y:ShapeNode>
</data>
</node>
</graph>
</node>
<node id="n8" yfiles.foldertype="group">
<data key="d4"/>
<data key="d6">
<y:ProxyAutoBoundsNode>
<y:Realizers active="0">
<y:GroupNode>
<y:Geometry height="142.37646484375" width="159.91864204406738" x="313.2978515625" y="224.62450218200684"/>
<y:Fill color="#FFCC0024" transparent="false"/>
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="node_width" backgroundColor="#FFCC00" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="22.37646484375" modelName="internal" modelPosition="t" textColor="#000000" visible="true" width="159.91864204406738" x="0.0" y="0.0">вхідний скрипт</y:NodeLabel>
<y:Shape type="rectangle"/>
<y:State closed="false" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
<y:Insets bottom="15" bottomF="15.0" left="15" leftF="15.0" right="15" rightF="15.0" top="15" topF="15.0"/>
<y:BorderInsets bottom="0" bottomF="0.0" left="1" leftF="0.9186420440673828" right="0" rightF="0.0" top="0" topF="0.0"/>
</y:GroupNode>
<y:GroupNode>
<y:Geometry height="50.0" width="50.0" x="313.2978515625" y="225.33495140075684"/>
<y:Fill color="#F5F5F5" transparent="false"/>
<y:BorderStyle color="#000000" type="dashed" width="1.0"/>
<y:NodeLabel alignment="right" autoSizePolicy="node_width" backgroundColor="#EBEBEB" borderDistance="0.0" fontFamily="Dialog" fontSize="15" fontStyle="plain" hasLineColor="false" height="22.37646484375" modelName="internal" modelPosition="t" textColor="#000000" visible="true" width="59.02685546875" x="-4.513427734375" y="0.0">Folder 4</y:NodeLabel>
<y:Shape type="roundrectangle"/>
<y:State closed="true" closedHeight="50.0" closedWidth="50.0" innerGraphDisplayEnabled="false"/>
<y:Insets bottom="5" bottomF="5.0" left="5" leftF="5.0" right="5" rightF="5.0" top="5" topF="5.0"/>
<y:BorderInsets bottom="0" bottomF="0.0" left="0" leftF="0.0" right="0" rightF="0.0" top="0" topF="0.0"/>
</y:GroupNode>
</y:Realizers>
</y:ProxyAutoBoundsNode>
</data>
<graph edgedefault="directed" id="n8:">
<node id="n8::n0">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="129.0" x="329.2164936065674" y="262.00096702575684"/>
<y:Fill color="#FFFFFF" 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="85.3984375" x="21.80078125" y="5.6494140625">завантаження
конфігурації<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="rectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n8::n1">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="129.0" x="329.2164936065674" y="322.00096702575684"/>
<y:Fill color="#FFFFFF" 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="82.052734375" x="23.4736328125" y="5.6494140625">запуск додатка<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="rectangle"/>
</y:ShapeNode>
</data>
</node>
</graph>
</node>
<edge id="e0" source="n2" target="n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#666666" type="line" width="2.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e1" source="n5" target="n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="-31.22050094604495" sy="-22.49430537223816" tx="0.0" ty="0.0"/>
<y:LineStyle color="#666666" type="line" width="2.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" hasText="false" height="4.0" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="4.0" x="28.00000600945461" y="-193.17557203769684">
<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="right" ratio="0.5" segment="0"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:EdgeLabel alignment="center" backgroundColor="#FFFFFF" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasLineColor="false" height="18.701171875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="17.34765625" x="-8.673822115545391" y="-200.52615797519684">11<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="center" ratio="0.5" segment="0"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e2" source="n6" target="n7::n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#666666" type="line" width="2.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" backgroundColor="#FFFFFF" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasLineColor="false" height="18.701171875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="10.673828125" x="-29.525518994973595" y="-10.349628448486328">3<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="0.9990329742431641" distanceToCenter="true" position="right" ratio="0.25395048761528816" segment="-1"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n7::e0" source="n7::n0" target="n7::n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#666666" type="line" width="2.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e3" source="n0" target="n8">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="-79.9882439360955" ty="0.0"/>
<y:LineStyle color="#666666" type="line" width="2.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" backgroundColor="#FFFFFF" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasLineColor="false" height="18.701171875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="10.673828125" x="36.76878085201736" y="-9.523307113000556">1<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="center" ratio="0.5" segment="0"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e4" source="n7::n1" target="n4">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="2.408647025755731" ty="-181.21658369302781"/>
<y:LineStyle color="#666666" type="line" width="2.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" backgroundColor="#FFFFFF" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasLineColor="false" height="18.701171875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="10.673828125" x="-4.962140296002758" y="18.61224679946895">4<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="30.0" distanceToCenter="false" position="center" ratio="0.5" segment="0"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e5" source="n3" target="n4::n2::n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#666666" type="line" width="2.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" backgroundColor="#FFFFFF" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasLineColor="false" height="18.701171875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="10.673828125" x="-30.100868416252297" y="-9.35060429573059">9<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="10.0" distanceToCenter="false" position="center" ratio="0.26448415477215953" segment="-1"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e6" source="n4::n2::n1" target="n5">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="-2.2737367544323206E-13" tx="0.0" ty="0.0"/>
<y:LineStyle color="#666666" type="line" width="2.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" backgroundColor="#FFFFFF" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasLineColor="false" height="18.701171875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="17.34765625" x="-83.18526519030615" y="-9.350604295730818">10<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="center" ratio="0.2786124840137136" segment="-1"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e7" source="n8::n1" target="n7">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="55.750299312644984" sy="0.355224609375" tx="-109.63961141576266" ty="42.066115379333496"/>
<y:LineStyle color="#666666" type="line" width="2.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" backgroundColor="#FFFFFF" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasLineColor="false" height="18.701171875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="10.673828125" x="29.326010704040527" y="-9.508390885372137">2<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="center" ratio="0.5" segment="0"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e8" source="n1" target="n4::n2::n0">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#666666" type="line" width="2.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" backgroundColor="#FFFFFF" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasLineColor="false" height="18.701171875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="10.673828125" x="-31.270312699786246" y="-10.35060429573059">8<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="1.0" distanceToCenter="true" position="right" ratio="0.2858946861565087" segment="-1"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e9" source="n4::n1" target="n5">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="-79.9882439360951" sy="2.2737367544323206E-13" tx="30.048898971244075" ty="-1.4999999999999991">
<y:Point x="287.93523844627487" y="544.3166599273684"/>
</y:Path>
<y:LineStyle color="#666666" type="line" width="2.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" backgroundColor="#FFFFFF" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasLineColor="false" height="18.701171875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="10.673828125" x="-76.70009317381192" y="-9.350576400756609">6<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="30.0" distanceToCenter="true" position="center" ratio="0.23459266172695797" segment="0"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n4::e0" source="n4::n0" target="n4::n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#666666" type="line" width="2.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" backgroundColor="#FFEFD6" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasLineColor="false" height="18.701171875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="10.673828125" x="-5.336933135986328" y="4.999985313415493">5<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="0.0" distance="30.0" distanceToCenter="true" position="center" ratio="0.0" segment="0"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n4::e1" source="n4::n1" target="n4::n2">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="-81.01828954355172"/>
<y:LineStyle color="#666666" type="line" width="2.0"/>
<y:Arrows source="none" target="standard"/>
<y:EdgeLabel alignment="center" backgroundColor="#FFEFD6" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasLineColor="false" height="18.701171875" modelName="custom" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="10.673828125" x="-5.4491733540852465" y="5.039560317993164">7<y:LabelModel>
<y:SmartEdgeLabelModel autoRotationEnabled="false" defaultAngle="0.0" defaultDistance="10.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartEdgeLabelModelParameter angle="6.283185307179586" distance="30.0" distanceToCenter="false" position="center" ratio="0.0" segment="0"/>
</y:ModelParameter>
<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
</y:EdgeLabel>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n4::n2::e0" source="n4::n2::n0" target="n4::n2::n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#666666" type="line" width="2.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="n8::e0" source="n8::n0" target="n8::n1">
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#666666" type="line" width="2.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">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;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="66px" viewBox="0 0 57 66" enable-background="new 0 0 57 66" xml:space="preserve"&gt;
&lt;g&gt;
&lt;linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="26.3799" y1="-2276.8809" x2="27.6209" y2="-2306.6792" gradientTransform="matrix(1 0 0 -1 0.2803 -2252.9199)"&gt;
&lt;stop offset="0.2711" style="stop-color:#FFAB4F"/&gt;
&lt;stop offset="1" style="stop-color:#FFD28F"/&gt;
&lt;/linearGradient&gt;
&lt;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"/&gt;
&lt;path id="body_13_" 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"/&gt;
&lt;path fill="#2068A3" stroke="#2068A3" d="M28.106,33.487c-8.112,0-12.688,4.312-12.688,10.437c0,7.422,12.688,10.438,12.688,10.438
s14.688-3.016,14.688-10.438C42.793,38.75,36.215,33.487,28.106,33.487z M26.288,53.051c0,0-7.135-2.093-8.805-7.201
c-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"/&gt;
&lt;radialGradient id="SVGID_2_" cx="14.2417" cy="9.1006" r="53.247" gradientTransform="matrix(1 0 0 -1 0.04 65.1543)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#74AEEE"/&gt;
&lt;stop offset="1" style="stop-color:#2068A3"/&gt;
&lt;/radialGradient&gt;
&lt;path fill="url(#SVGID_2_)" stroke="#2068A3" stroke-miterlimit="10" d="M49.529,51.225c-2.239-2.24-5.041-3.724-7.396-4.67
c-2.854,5.51-14.022,7.807-14.022,7.807s-10.472-2.484-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.947,0,3.521-1.558,3.521-3.492
C56.055,62.768,54.211,55.906,49.529,51.225z"/&gt;
&lt;path fill="#5491CF" stroke="#2068A3" d="M13.404,44.173c1.15-1.81,2.039-3.832,3.332-5.397c-0.514,1.027-1.669,4.084-1.669,5.148
c0,5.186,10.366,9.079,14.688,10.438c-3.472,1.627-9.134-1.498-11.335-2.36c-3.601-1.419-4.071-3.063-5.89-4.854
C12.523,47.135,12.878,45,13.404,44.173z"/&gt;
&lt;path fill="#5491CF" stroke="#2068A3" d="M45.777,43.924c-1.317-1.568-5.11-9.424-6.604-6.617c0.516,1.025,3.617,3.693,3.617,6.617
c0,5.186-10.27,8.576-16.698,9.145c1.429,4.938,11.372,1.293,13.804-0.313c3.563-2.354,4.563-5.133,7.854-3.705
C47.754,49.045,48.006,46.574,45.777,43.924z"/&gt;
&lt;path fill="none" stroke="#2068A3" stroke-linecap="round" 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"/&gt;
&lt;path fill="none" stroke="#2068A3" stroke-linecap="round" 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"/&gt;
&lt;radialGradient id="face_x5F_white_1_" cx="27.623" cy="-2278.646" r="23.425" fx="23.0534" fy="-2281.1357" gradientTransform="matrix(1 0 0 -1 0.2803 -2252.9199)" gradientUnits="userSpaceOnUse"&gt;
&lt;stop offset="0" style="stop-color:#FFD28F"/&gt;
&lt;stop offset="1" style="stop-color:#FFAB4F"/&gt;
&lt;/radialGradient&gt;
&lt;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"/&gt;
&lt;linearGradient id="face_highlight_1_" gradientUnits="userSpaceOnUse" x1="5761.7578" y1="11330.6484" x2="5785.3872" y2="11424.0977" gradientTransform="matrix(0.275 0 0 0.2733 -1558.9874 -3088.4209)"&gt;
&lt;stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.24"/&gt;
&lt;stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0.16"/&gt;
&lt;/linearGradient&gt;
&lt;path id="face_highlight_3_" fill="url(#face_highlight_1_)" d="M27.958,6.333c-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.083,13.952,36.271,6.268,27.958,6.333z"/&gt;
&lt;path id="Hair_Young_Brown_1_" fill="#CC9869" stroke="#99724F" 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"/&gt;
&lt;path fill="#4B4B4B" stroke="#4B4B4B" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M28.105,2
C22.464,2,20.2,4.246,18.13,5.533C29.753,2.865,41.152,10.375,44.46,20.5C44.459,16.875,44.459,2,28.105,2z"/&gt;
&lt;path fill="#9B9B9B" stroke="#4B4B4B" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M11.151,17.751
C12.878,8.25,18.686,6.309,25.273,7.127C31.295,7.875,36.93,10.491,44.459,20.5C37.777,7.125,20.278-3.375,9.903,3.921
C5.569,6.97,4.903,13.375,11.151,17.751z"/&gt;
&lt;/g&gt;
&lt;/svg&gt;
</y:Resource>
<y:Resource id="2">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" width="41px" height="48px" viewBox="-0.875 -0.887 41 48" enable-background="new -0.875 -0.887 41 48"
xml:space="preserve"&gt;
&lt;defs&gt;
&lt;/defs&gt;
&lt;linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="642.8008" y1="-979.1445" x2="682.0508" y2="-979.1445" gradientTransform="matrix(1 0 0 -1 -642.8008 -939.4756)"&gt;
&lt;stop offset="0" style="stop-color:#3C89C9"/&gt;
&lt;stop offset="0.1482" style="stop-color:#60A6DD"/&gt;
&lt;stop offset="0.3113" style="stop-color:#81C1F0"/&gt;
&lt;stop offset="0.4476" style="stop-color:#95D1FB"/&gt;
&lt;stop offset="0.5394" style="stop-color:#9CD7FF"/&gt;
&lt;stop offset="0.636" style="stop-color:#98D4FD"/&gt;
&lt;stop offset="0.7293" style="stop-color:#8DCAF6"/&gt;
&lt;stop offset="0.8214" style="stop-color:#79BBEB"/&gt;
&lt;stop offset="0.912" style="stop-color:#5EA5DC"/&gt;
&lt;stop offset="1" style="stop-color:#3C89C9"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_1_)" d="M19.625,36.763C8.787,36.763,0,34.888,0,32.575v10c0,2.313,8.787,4.188,19.625,4.188
c10.839,0,19.625-1.875,19.625-4.188v-10C39.25,34.888,30.464,36.763,19.625,36.763z"/&gt;
&lt;linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="642.8008" y1="-973.1445" x2="682.0508" y2="-973.1445" gradientTransform="matrix(1 0 0 -1 -642.8008 -939.4756)"&gt;
&lt;stop offset="0" style="stop-color:#9CD7FF"/&gt;
&lt;stop offset="0.0039" style="stop-color:#9DD7FF"/&gt;
&lt;stop offset="0.2273" style="stop-color:#BDE5FF"/&gt;
&lt;stop offset="0.4138" style="stop-color:#D1EEFF"/&gt;
&lt;stop offset="0.5394" style="stop-color:#D9F1FF"/&gt;
&lt;stop offset="0.6155" style="stop-color:#D5EFFE"/&gt;
&lt;stop offset="0.6891" style="stop-color:#C9E7FA"/&gt;
&lt;stop offset="0.7617" style="stop-color:#B6DAF3"/&gt;
&lt;stop offset="0.8337" style="stop-color:#9AC8EA"/&gt;
&lt;stop offset="0.9052" style="stop-color:#77B0DD"/&gt;
&lt;stop offset="0.9754" style="stop-color:#4D94CF"/&gt;
&lt;stop offset="1" style="stop-color:#3C89C9"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_2_)" d="M19.625,36.763c10.839,0,19.625-1.875,19.625-4.188l-1.229-2c0,2.168-8.235,3.927-18.396,3.927
c-9.481,0-17.396-1.959-18.396-3.927l-1.229,2C0,34.888,8.787,36.763,19.625,36.763z"/&gt;
&lt;path fill="#3C89C9" d="M19.625,26.468c10.16,0,19.625,2.775,19.625,2.775c-0.375,2.721-5.367,5.438-19.554,5.438
c-12.125,0-18.467-2.484-19.541-4.918C-0.127,29.125,9.465,26.468,19.625,26.468z"/&gt;
&lt;linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="642.8008" y1="-965.6948" x2="682.0508" y2="-965.6948" gradientTransform="matrix(1 0 0 -1 -642.8008 -939.4756)"&gt;
&lt;stop offset="0" style="stop-color:#3C89C9"/&gt;
&lt;stop offset="0.1482" style="stop-color:#60A6DD"/&gt;
&lt;stop offset="0.3113" style="stop-color:#81C1F0"/&gt;
&lt;stop offset="0.4476" style="stop-color:#95D1FB"/&gt;
&lt;stop offset="0.5394" style="stop-color:#9CD7FF"/&gt;
&lt;stop offset="0.636" style="stop-color:#98D4FD"/&gt;
&lt;stop offset="0.7293" style="stop-color:#8DCAF6"/&gt;
&lt;stop offset="0.8214" style="stop-color:#79BBEB"/&gt;
&lt;stop offset="0.912" style="stop-color:#5EA5DC"/&gt;
&lt;stop offset="1" style="stop-color:#3C89C9"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_3_)" d="M19.625,23.313C8.787,23.313,0,21.438,0,19.125v10c0,2.313,8.787,4.188,19.625,4.188
c10.839,0,19.625-1.875,19.625-4.188v-10C39.25,21.438,30.464,23.313,19.625,23.313z"/&gt;
&lt;linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="642.8008" y1="-959.6948" x2="682.0508" y2="-959.6948" gradientTransform="matrix(1 0 0 -1 -642.8008 -939.4756)"&gt;
&lt;stop offset="0" style="stop-color:#9CD7FF"/&gt;
&lt;stop offset="0.0039" style="stop-color:#9DD7FF"/&gt;
&lt;stop offset="0.2273" style="stop-color:#BDE5FF"/&gt;
&lt;stop offset="0.4138" style="stop-color:#D1EEFF"/&gt;
&lt;stop offset="0.5394" style="stop-color:#D9F1FF"/&gt;
&lt;stop offset="0.6155" style="stop-color:#D5EFFE"/&gt;
&lt;stop offset="0.6891" style="stop-color:#C9E7FA"/&gt;
&lt;stop offset="0.7617" style="stop-color:#B6DAF3"/&gt;
&lt;stop offset="0.8337" style="stop-color:#9AC8EA"/&gt;
&lt;stop offset="0.9052" style="stop-color:#77B0DD"/&gt;
&lt;stop offset="0.9754" style="stop-color:#4D94CF"/&gt;
&lt;stop offset="1" style="stop-color:#3C89C9"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_4_)" d="M19.625,23.313c10.839,0,19.625-1.875,19.625-4.188l-1.229-2c0,2.168-8.235,3.926-18.396,3.926
c-9.481,0-17.396-1.959-18.396-3.926l-1.229,2C0,21.438,8.787,23.313,19.625,23.313z"/&gt;
&lt;path fill="#3C89C9" d="M19.476,13.019c10.161,0,19.625,2.775,19.625,2.775c-0.375,2.721-5.367,5.438-19.555,5.438
c-12.125,0-18.467-2.485-19.541-4.918C-0.277,15.674,9.316,13.019,19.476,13.019z"/&gt;
&lt;linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="642.8008" y1="-952.4946" x2="682.0508" y2="-952.4946" gradientTransform="matrix(1 0 0 -1 -642.8008 -939.4756)"&gt;
&lt;stop offset="0" style="stop-color:#3C89C9"/&gt;
&lt;stop offset="0.1482" style="stop-color:#60A6DD"/&gt;
&lt;stop offset="0.3113" style="stop-color:#81C1F0"/&gt;
&lt;stop offset="0.4476" style="stop-color:#95D1FB"/&gt;
&lt;stop offset="0.5394" style="stop-color:#9CD7FF"/&gt;
&lt;stop offset="0.636" style="stop-color:#98D4FD"/&gt;
&lt;stop offset="0.7293" style="stop-color:#8DCAF6"/&gt;
&lt;stop offset="0.8214" style="stop-color:#79BBEB"/&gt;
&lt;stop offset="0.912" style="stop-color:#5EA5DC"/&gt;
&lt;stop offset="1" style="stop-color:#3C89C9"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_5_)" d="M19.625,10.113C8.787,10.113,0,8.238,0,5.925v10c0,2.313,8.787,4.188,19.625,4.188
c10.839,0,19.625-1.875,19.625-4.188v-10C39.25,8.238,30.464,10.113,19.625,10.113z"/&gt;
&lt;linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="642.8008" y1="-946.4946" x2="682.0508" y2="-946.4946" gradientTransform="matrix(1 0 0 -1 -642.8008 -939.4756)"&gt;
&lt;stop offset="0" style="stop-color:#9CD7FF"/&gt;
&lt;stop offset="0.0039" style="stop-color:#9DD7FF"/&gt;
&lt;stop offset="0.2273" style="stop-color:#BDE5FF"/&gt;
&lt;stop offset="0.4138" style="stop-color:#D1EEFF"/&gt;
&lt;stop offset="0.5394" style="stop-color:#D9F1FF"/&gt;
&lt;stop offset="0.6155" style="stop-color:#D5EFFE"/&gt;
&lt;stop offset="0.6891" style="stop-color:#C9E7FA"/&gt;
&lt;stop offset="0.7617" style="stop-color:#B6DAF3"/&gt;
&lt;stop offset="0.8337" style="stop-color:#9AC8EA"/&gt;
&lt;stop offset="0.9052" style="stop-color:#77B0DD"/&gt;
&lt;stop offset="0.9754" style="stop-color:#4D94CF"/&gt;
&lt;stop offset="1" style="stop-color:#3C89C9"/&gt;
&lt;/linearGradient&gt;
&lt;path fill="url(#SVGID_6_)" d="M19.625,10.113c10.839,0,19.625-1.875,19.625-4.188l-1.229-2c0,2.168-8.235,3.926-18.396,3.926
c-9.481,0-17.396-1.959-18.396-3.926L0,5.925C0,8.238,8.787,10.113,19.625,10.113z"/&gt;
&lt;linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="644.0293" y1="-943.4014" x2="680.8223" y2="-943.4014" gradientTransform="matrix(1 0 0 -1 -642.8008 -939.4756)"&gt;
&lt;stop offset="0" style="stop-color:#9CD7FF"/&gt;
&lt;stop offset="1" style="stop-color:#3C89C9"/&gt;
&lt;/linearGradient&gt;
&lt;ellipse fill="url(#SVGID_7_)" cx="19.625" cy="3.926" rx="18.396" ry="3.926"/&gt;
&lt;path opacity="0.24" fill="#FFFFFF" enable-background="new " d="M31.04,45.982c0,0-4.354,0.664-7.29,0.781
c-3.125,0.125-8.952,0-8.952,0l-2.384-10.292l0.044-2.108l-1.251-1.154L9.789,23.024l-0.082-0.119L9.5,20.529l-1.65-1.254
L5.329,8.793c0,0,4.213,0.903,7.234,1.07s8.375,0.25,8.375,0.25l3,9.875l-0.25,1.313l1.063,2.168l2.312,9.645l-0.521,1.416
l1.46,1.834L31.04,45.982z"/&gt;
&lt;/svg&gt;
</y:Resource>
</y:Resources>
</data>
</graphml>
Робота з базами даних
======================
=====================
Цей розділ описує, як створити нову сторінку, яка буде відображати назву країни, отриману з таблиці бази даних `country`. Для досягнення цієї мети, вам необхідно буде налаштувати з'єднання з базою даних, отримати необхідні дані з допомогою класу [Active Record](db-active-record.md), створити [подію](structure-controllers.md),
і зобразити все в [представленні](structure-views.md).
Цей розділ описує, як створити нову сторінку, яка буде відображати дані країни, отримані з таблиці бази даних `country`.
Для цього, вам необхідно буде налаштувати зʼєднання з базою даних, створити клас [Active Record](db-active-record.md),
визначити [дію](structure-controllers.md) та створити [представлення](structure-views.md).
З допомогою даного посібника ви дізнаєтесь як:
За допомогою даного посібника ви дізнаєтесь як:
* Налаштувати зєднання з базою даних
* Налаштувати зʼєднання з базою даних
* Оголосити Active Record класс
* Створювати запити використовуючи Active Record клас
* Відображати дані в представленні з нумерацією сторінок
* Запитувати дані за допомогою класу Active Record
* Відображати дані у представленні із розбиттям по сторінках
Зверніть увагу, що для того, щоб закінчити цей розділ, ви повинні мати базові знання і досвід використання баз даних. Зокрема, ви повинні знати, як створювати бази даних, як виконувати SQL-запити , використовуючи клієнти баз даних.
Зверніть увагу, що для того, щоб закінчити цей розділ, ви повинні мати базові знання і досвід використання баз даних.
Зокрема, ви повинні знати, як створювати бази даних, як виконувати SQL-запити за допомогою клієнтських додатків баз даних.
Підготовка бази даних <a name="preparing-database"></a>
--------------------
---------------------
Для початку створіть базу даних `yii2basic`, з якої і будете надалі отримувати дані. Ви можете використовувати SQLite, MySQL, PostgreSQL, MSSQL або Oracle бази даних, Yii має вбудовану підтримку для багатьох баз даних.
Для початку, створіть базу даних `yii2basic`, з якої і будете надалі отримувати дані.
Ви можете використовувати SQLite, MySQL, PostgreSQL, MSSQL або Oracle бази даних, Yii має вбудовану підтримку для багатьох баз даних.
Для простоти, будемо вважати що використовується MySQL у подальшому описі.
Далі, створіть таблицю `country`, і внесіть декілька прикладів. Можете використати наступний SQL-запит, як приклад:
......@@ -43,11 +47,13 @@ INSERT INTO `country` VALUES ('US','United States',278357000);
На даний момент, у вас є база даних `yii2basic` і таблиця `country` з трьома колонками, що містять десять рядків даних.
Налаштування підключення до БД <a name="configuring-db-connection"></a>
---------------------------
------------------------------
Перш ніж продовжити, переконайтеся, що у вас налаштовано [PDO](http://www.php.net/manual/en/book.pdo.php) PHP розширення і PDO драйвер для вашої БД (наприклад `pdo_mysql` для MySQL). Це є основною вимогою якщо ваш додаток використовує реляційну базу даних.
Перш ніж продовжити, переконайтеся, що у вас налаштовано [PDO](http://www.php.net/manual/en/book.pdo.php) PHP розширення
і PDO драйвер для вашої БД (наприклад `pdo_mysql` для MySQL). Це є основною вимогою, якщо ваш додаток використовує реляційну базу даних.
Згідно того, що у вас встановлено, відкрийте файл `config/db.php` і замініть на коректні дані вашої БД. За замовчуванням, файл містить наступне:
Згідно того, що у вас встановлено, відкрийте файл `config/db.php` і замініть на коректні дані вашої БД.
За замовчуванням, файл містить наступне:
```php
<?php
......@@ -61,18 +67,22 @@ return [
];
```
Файл конфігурації `config/db.php` є типовим інструментом на основі файлів [налаштування](concept-configurations.md). Даний файл конфігурації визначає параметри, які необхідні для створення і ініціалізації [[yii\db\Connection]] примірника, через який ви можете робити SQL-запити до основної бази даних.
Файл конфігурації `config/db.php` є типовим інструментом [налаштування](concept-configurations.md) на основі файлів.
Даний файл конфігурації визначає параметри, які необхідні для створення і ініціалізації [[yii\db\Connection]] примірника,
через який ви можете робити SQL-запити до основної бази даних.
З’єднання з БД описане вище може бути доступне в коді програми за допомогою виразу `Yii::$app->db`.
З’єднання з БД, описане вище, може бути доступне в коді додатка за допомогою виразу `Yii::$app->db`.
> Інформація: Файл конфігурації `config/db.php` буде включений до конфігурації головного додатка `config/web.php`, який визначає як має бути проініційований сам [додаток](structure-applications.md).
Для отримання додаткової інформації, будь ласка, зверніться до розділу [Налаштування](concept-configurations.md).
> Інформація: Файл конфігурації `config/db.php` буде включений до конфігурації головного додатка `config/web.php`,
який визначає як має бути проініційований сам [додаток](structure-applications.md). Для отримання додаткової інформації,
будь ласка, зверніться до розділу [Налаштування](concept-configurations.md).
Створення Active Record <a name="creating-active-record"></a>
-------------------------
-----------------------
Для відображення і отримання даних з таблиці `country` створіть [Active Record](db-active-record.md) клас з іменем `Country`, і збережіть в файл `models/Country.php`.
Для відображення і отримання даних з таблиці `country` створіть [Active Record](db-active-record.md) клас
з іменем `Country`, і збережіть в файл `models/Country.php`.
```php
<?php
......@@ -86,17 +96,18 @@ class Country extends ActiveRecord
}
```
Клас `Country` наслідує [[yii\db\ActiveRecord]]. Вам не потрібно писати ніякого коду всередині нього! Всього лише за допомогою описаного вище коду,
Yii отримає відповідне ім'я таблиці з імені класу.
Клас `Country` наслідує [[yii\db\ActiveRecord]]. Вам не потрібно писати ніякого коду всередині нього!
Всього лише за допомогою описаного вище коду, Yii самостійно вгадає відповідне імʼя таблиці з імені класу.
> Інформація: Якщо немає прямого співпадіння з імені класу і таблиці, ви можете використати метод [[yii\db\ActiveRecord::tableName()]] щоб задати відповідне ім'я таблиці.
> Інформація: Якщо немає прямого співпадіння з імені класу і таблиці,
ви можете використати метод [[yii\db\ActiveRecord::tableName()]] щоб задати відповідне імʼя таблиці.
Використовуючи клас `Country`, ви можете легко маніпулювати даними з таблиці `country`, як показано в наступному фрагменті:
```php
use app\models\Country;
// отримати всі рядки з таблиці country і замовити їх по "name"
// отримати всі рядки з таблиці country і відсортувати їх по "name"
$countries = Country::find()->orderBy('name')->all();
// отримати рядок, по основному ключу "US"
......@@ -110,13 +121,17 @@ $country->name = 'U.S.A.';
$country->save();
```
> Інформація: Active Record є потужним засобом для доступу і управління даними в базі даних в об'єктно-орієнтованому стилі. Ви можете знайти більш детальну інформацію в розділі [Active Record](db-active-record.md). Крім того, ви також можете взаємодіяти з базою даних, використовуючи для доступу метод передачі даних нижнього рівня під назвою [Data Access Objects](db-dao.md).
> Інформація: Active Record є потужним засобом для доступу і управління даними в базі даних в обʼєктно-орієнтованому стилі.
Ви можете знайти більш детальну інформацію в розділі [Active Record](db-active-record.md). Крім того, ви також можете
взаємодіяти з базою даних, використовуючи для доступу метод передачі даних нижнього рівня під назвою [Data Access Objects](db-dao.md).
Створення події <a name="creating-action"></a>
------------------
Створення дії <a name="creating-action"></a>
-------------
Щоб відобразити дані про країну кінцевим користувачам, необхідно створити нову подію. Замість розміщення нової події в контролері `site`, який ви використовували в попередніх розділах, є сенс створити новий контролер спеціально для всіх подій пов’язаних з даними таблиці країн. Створіть навий контролер з іменем `CountryController` і подію `index`, як показано нижще.
Щоб відобразити дані про країну кінцевим користувачам, необхідно створити нову дію. Замість розміщення нової дії
у контролері `site`, який ви використовували в попередніх розділах, є сенс створити новий контролер спеціально для всіх дій,
пов’язаних з даними країн. Створіть новий контролер з іменем `CountryController` і дію `index`, як показано нижче:
```php
<?php
......@@ -153,21 +168,23 @@ class CountryController extends Controller
Збережіть цей код у файл `controllers/CountryController.php`.
Подія `index` викликає метод `Country::find()`. Цей Active Record метод будує запит і отримує всі дані з таблиці `country`.
Щоб обмежити кількість країн, які будуть отримуватись в кожному запиті, сам запит розбивається на сторінки, за допомогою
[[yii\data\Pagination]] об'єкта. Об’єкт `Pagination` служить двом цілям:
Дія `index` викликає метод `Country::find()`. Цей метод Active Record будує запит бази даних і отримує всі дані з таблиці `country`.
Щоб обмежити кількість країн, які будуть отримуватись в кожному запиті, сам запит розбивається на сторінки, за допомогою об’єкта
[[yii\data\Pagination]]. Об’єкт `Pagination` служить двом цілям:
* Встановлює `положення` і `ліміт` для SQL-запиту так, щоб він повертав лише одну сторінку даних за один раз (не більше 5 рядків в сторінці).
* Використовується в цілях відображення пейджера, що складається зі списку кнопок сторінок, як буде описано в наступному підрозділі.
* Встановлює `offset` і `limit` для SQL-запиту так, щоб він повертав лише одну сторінку даних за один раз
(не більше 5 рядків на сторінці).
* Використовується у представленнях для відображення пейджера, який складається із переліку кнопок переходу по сторінкам,
про що буде описано у наступному підрозділі.
Наприкінці, подія `index` повертає представлення `index` і передає дані по країнах, з розбивкою на сторінки.
Наприкінці, дія `index` повертає представлення `index` і передає дані по країнах, з розбивкою на сторінки.
Створення представлення <a name="creating-view"></a>
---------------
-----------------------
В директорії `views` створіть спочатку підкаталог `country`. Цей каталог буде використовуватись для всіх представленнь контролера `country`. В каталозі `views/country`, створіть файл з іменем`index.php`
що містить наступне:
В директорії `views` створіть спочатку підкаталог `country`. Цей каталог буде використовуватись для всіх представленнь
контролера `country`. В каталозі `views/country`, створіть файл з іменем`index.php` що містить наступне:
```php
<?php
......@@ -187,12 +204,14 @@ use yii\widgets\LinkPager;
<?= LinkPager::widget(['pagination' => $pagination]) ?>
```
Дане представлення містить два розділи для відображення даних по країнам. У першій частині, відображаються дані про країни у вигляді невпорядкованого списку HTML. У другій частині, [[yii\widgets\LinkPager]] віджет з використанням інформації про нумерацію сторінок.
`LinkPager` віджет показується у вигляді списку кнопок. При натисканні на будь-якій з них будуть оновлюватись дані країн у відповідній сторінці.
Дане представлення містить два розділи для відображення даних по країнам. У першій частині, відображаються дані про країни
у вигляді невпорядкованого списку HTML. У другій частині, [[yii\widgets\LinkPager]] віджет з використанням інформації
про нумерацію сторінок. Віджет `LinkPager` відображаться у вигляді переліку кнопок.
При натисканні на будь-якій з них будуть оновлюватись дані країн на відповідній сторінці.
Спробуєм <a name="trying-it-out"></a>
-------------
--------
Щоб побачити все, що було створено під час роботи, відкрийте в браузері наступний URL:
......@@ -200,28 +219,35 @@ use yii\widgets\LinkPager;
http://hostname/index.php?r=country/index
```
![Перелік країн](../guide/images/start-country-list.png)
![Перелік країн](images/start-country-list.png)
Спочатку, ви побачите сторінку з переліком п'яти країн. Нижче країн, ви побачите пейджер з чотирма кнопками.
Якщо ви натиснете на кнопку "2", ви побачите сторінку ще п'ять країн з бази даних: другу сторінку записів.
Спочатку, ви побачите сторінку з переліком пʼяти країн. Нижче країн, ви побачите пейджер з чотирма кнопками.
Якщо ви натиснете на кнопку "2", ви побачите сторінку з іншими пʼятьма країнами з бази даних: другу сторінку записів.
Придивившись більш уважно, ви побачите, що URL в браузері також змінюється на
```
http://hostname/index.php?r=country/index&page=2
```
За лаштунками, [[yii\data\Pagination|Pagination]] надає всю необхідну функціональність для розбивки набору даних на сторінки:
За лаштунками, [[yii\data\Pagination|Pagination]] надає всю необхідну функціональність для розбиття набору даних на сторінки:
* Спочатку, [[yii\data\Pagination|Pagination]] представляє першу сторінку, яка відображає країни запитом SELECT з умовою `LIMIT 5 OFFSET 0`. В результаті, будуть відображені перші знайдені п'ять країн.
* [[yii\widgets\LinkPager|LinkPager]] віджет відображає кнопки сторінок з URL-адресами створеними за допомогою [[yii\data\Pagination::createUrl()|Pagination]]. URL-адреси будуть містити параметр запиту `page`, який представляє різні номери сторінок.
* Спочатку, [[yii\data\Pagination|Pagination]] представляє першу сторінку, яка відображає країни запитом SELECT
з умовою `LIMIT 5 OFFSET 0`. В результаті, будуть відображені перші знайдені пʼять країн.
* [[yii\widgets\LinkPager|LinkPager]] віджет відображає кнопки сторінок з URL-адресами створеними за допомогою
[[yii\data\Pagination::createUrl()|Pagination]]. URL-адреси будуть містити параметр запиту `page`,
який представляє різні номери сторінок.
* Якщо ви натиснете кнопку "2", спрацює новий запит, який буде відправлений на `country/index` з подальшим опрацюванням.
[[yii\data\Pagination|Pagination]] зчитає параметр `page` з URL-запиту і встановить номер поточної сторінки в 2-ку.
Таким чином, новий запит буде мати пункт `LIMIT 5 OFFSET 5` і поверне наступні п'ять країн для відображення.
Таким чином, новий запит буде мати визначення `LIMIT 5 OFFSET 5` і поверне наступні пʼять країн для відображення.
Резюме <a name="summary"></a>
-------
Підсумок <a name="summary"></a>
--------
В цьому розділі ви дізналися, як працювати з базою даних. Ви також дізналися, як вибирати і відображати дані на сторінках за допомогою [[yii\data\Pagination]] і [[yii\widgets\LinkPager]].
В цьому розділі ви дізналися, як працювати з базою даних. Ви також дізналися, як вибирати і відображати дані на сторінках
за допомогою [[yii\data\Pagination]] і [[yii\widgets\LinkPager]].
У наступному розділі ви дізнаєтеся, як використовувати потужний інструмент генерації коду, що називається [Gii](tool-gii.md), який допоможе вам швидко здійснювати деякі часто необхідні функції, такі як Create-Read-Update-Delete (CRUD) операції для роботи з даними в таблицях баз даних. Насправді, код, який ви щойно написали, Yii може автоматично сгенерувати з допомогою функції Gii.
У наступному розділі ви дізнаєтеся, як використовувати потужний інструмент генерації коду, що називається [Gii](tool-gii.md),
який допоможе вам швидко здійснювати деякі часто необхідні функції, такі як Create-Read-Update-Delete (CRUD)
операції для роботи з даними в таблицях баз даних.
Насправді, код, який ви щойно написали, Yii може автоматично сгенерувати з допомогою функції Gii.
Робота з формами
================
В даному розділі ми обговоримо отримання даних від користувачів. На сторінці буде розміщена форма з полями, де можна буде вказати ім’я та email. Отримані дані будуть зображені на сторінці для їх підтвердження.
В даному розділі ми обговоримо отримання даних від користувачів. На сторінці буде розміщена форма з полями,
де можна буде вказати ім’я та email. Отримані дані будуть зображені на сторінці для їх підтвердження.
Для того, щоб досягти дану ціль, крім створення [події](structure-controllers.md) і двох [представлень](structure-views.md)
Для того, щоб досягти дану ціль, крім створення [дії](structure-controllers.md) і двох [представлень](structure-views.md)
ви створите [модель](structure-models.md).
В даному керівництві ви дізнаєтесь:
* Як створити [модель](structure-models.md) для даних, вказаних користувачем;
* Як оголосити правила перевірки переданих даних;
* Як створити HTML форму в [представлені](structure-views.md).
* Як створити [модель](structure-models.md) для даних, вказаних користувачем
* Як оголосити правила перевірки введених даних
* Як створити HTML форму в [представленні](structure-views.md)
Створення моделі <a name="creating-model"></a>
---------------------------------------------
----------------
У файлі `models/EntryForm.php` створіть клас моделі `EntryForm` як показано нижче. Він буде використовуватись для зберігання даних, вказаних користувачем. Детальніше про присвоєння імен файлам класів читайте в розділі
«[Автозавантаження класів](concept-autoloading.md)».
Створіть клас моделі `EntryForm` та збережіть у файлі `models/EntryForm.php` як показано нижче. Він буде використовуватись
для зберігання даних, введених користувачем. Детальніше про присвоєння імен файлам класів читайте в розділі
[Автозавантаження класів](concept-autoloading.md).
```php
<?php
......@@ -43,21 +45,40 @@ class EntryForm extends Model
Даний клас розширює клас [[yii\base\Model]], який є складовою частиною фреймворка і зазвичай використовується для роботи з даними форм.
> Інформація: Клас [[yii\base\Model]] використовується як батьківський клас для класів моделей, які *не* асоційовані
з таблицями бази даних. Клас [[yii\db\ActiveRecord]] зазвичай є батьківським для класів моделей, що відповідають
таблицям бази даних.
Клас містить 2 публічні властивості `name` і `email`, які використовуються для зберігання даних, вказаних користувачем.
Він також містить метод `rules()`, який повертає набір правил поведінки даних. Правила, оголошені в коді вище означають наступне:
Він також містить метод `rules()`, який повертає набір правил перевірки даних. Правила перевірки,
оголошені в коді вище означають наступне:
* Поля `name` і `email` обов’язкові для заповнення;
* Поле `email` повино містити правильну адресу email.
* Поля `name` і `email` обов’язкові для заповнення
* Поле `email` повино містити правильну адресу email
Якщо об’єкт `EntryForm` заповнений даними користувача, то для їх перевірки ви можете викликати метод
[[yii\base\Model::validate()|validate()]]. У випадку невдалої перевірки властивість [[yii\base\Model::hasErrors|hasErrors]]
дорівнюватиме `true`. За допомогою [[yii\base\Model::getErrors|errors]] можна дізнатись, які саме виникли помилки.
```php
<?php
$model = new EntryForm();
$model->name = 'Qiang';
$model->email = 'bad';
if ($model->validate()) {
// Good!
} else {
// Failure!
// Use $model->getErrors()
}
```
Створення події <a name="creating-action"></a>
------------------------------------------------
Створення дії <a name="creating-action"></a>
-------------
Далі створіть подію `entry` в контролері `site`, точно так, як ви робили це раніше.
Далі створіть дію `entry` в контролері `site`, точно так, як ви робили це раніше.
Процес створення та використання дій описано у розділі [Говоримо «Привіт»](start-hello.md).
```php
<?php
......@@ -77,7 +98,7 @@ class SiteController extends Controller
$model = new EntryForm;
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
// дані в $model успішно провірені
// дані в $model успішно перевірені
// робимо щось корисне з $model ...
......@@ -91,21 +112,25 @@ class SiteController extends Controller
```
Подія створює об’єкт `EntryForm`. Потім вона намагається заповнити модель даними із масива `$_POST`, доступ
до якого забеспечує Yii за допомогою [[yii\web\Request::post()]]. Якщо модель успішно заповнена, тобто користувач відправив дані з HTML форми, то для перевірки даних буде викликаний метод [[yii\base\Model::validate()|validate()]].
до якого забеспечує Yii за допомогою [[yii\web\Request::post()]]. Якщо модель успішно заповнена, тобто користувач відправив
дані з HTML форми, то для перевірки даних буде викликаний метод [[yii\base\Model::validate()|validate()]].
> Інформація: `Yii::$app` являє собою глобально доступний екземпляр-одинак [додатка](structure-applications.md)
(singleton). Одночасно це є [Service Locator](concept-service-locator.md), який надає доступ до компонентів, типу
`request`, `response`, `db` і так далі. В коді выще для доступу до даних з `$_POST` був використаний компонент `request`.
Якщо все гаразд, подія зобразить представлення `entry-confirm`, яке покаже користувачу вказані ним дані.
В іншому випадку буде зображено представлення `entry`, яке містить HTML форму і помилки перевірки даних, якщо вони є.
> Інформація: `Yii::$app` являє собою глобально доступний екземпляр-одинак
[додатка](structure-applications.md) (singleton). Одночасно це [Service Locator](concept-service-locator.md),
який надає доступ до компонентів типу `request`, `response`, `db` і так далі. В коді выще для доступу до даних з `$_POST`
був використаний компонент `request`.
> Примітка: У цьому дуже простому прикладі ми просто відобразили сторінку підтвердження відправки даних.
На практиці, ви повинні розглянути використання [[yii\web\Controller::refresh()|refresh()]] або [[yii\web\Controller::redirect()|redirect()]]
для уникнення [проблеми повторного відправлення даних форми](http://en.wikipedia.org/wiki/Post/Redirect/Get).
Створення представлення <a name="creating-views"></a>
----------------------------------------------------
-----------------------
В завершення, створюємо два представлення з іменами `entry-confirm` і `entry`, котрі зображаються подією `entry` з минулого підрозділа.
На завершення, створюємо два представлення з іменами `entry-confirm` і `entry`, котрі зображаються дією `entry` з минулого підрозділу.
Представлення `entry-confirm` просто зображає ім’я та email. Воно мусить бути збережене у файлі `views/site/entry-confirm.php`.
......@@ -142,14 +167,15 @@ use yii\widgets\ActiveForm;
```
Для побудови HTML форми представлення використовує потужний [віджет](structure-widgets.md) [[yii\widgets\ActiveForm|ActiveForm]].
Методи `begin()` і `end()` виводять відкриваючий і закриваючий теги форми. Між цими викликами створюються поля для заповнення за допомогою метода [[yii\widgets\ActiveForm::field()|field()]]. Першим іде поле для "name", другим — для "email".
Методи `begin()` і `end()` виводять відкриваючий і закриваючий теги форми. Між цими викликами створюються поля для заповнення
за допомогою метода [[yii\widgets\ActiveForm::field()|field()]]. Першим іде поле для "name", другим — для "email".
Далі для генерації кнопки відправлення даних викликається метод [[yii\helpers\Html::submitButton()]].
Спробуєм <a name="trying-it-out"></a>
--------------------------------------
Спробуємо <a name="trying-it-out"></a>
---------
Щоб побачити все, що було створено під час роботи, відкрийте в браузері наступний URL:
Щоб побачити, як це працює, відкрийте в браузері наступний URL:
```
http://hostname/index.php?r=site/entry
......@@ -159,21 +185,27 @@ http://hostname/index.php?r=site/entry
інформацію слід вказувати. Якщо ви натиснете на кнопку відправлення даних без самих даних або якщо вкажете email в невірному
форматі, то ви побачите повідомлення з помилкою біля кожного проблемного поля.
![Форма з помилками](../guide/images/start-form-validation.png)
![Форма з помилками](images/start-form-validation.png)
Після введення вірних даних і їх відправки, ви побачите сторінку з даними, які щойно вказали.
![Підтвердження введених даних](../guide/images/start-entry-confirmation.png)
![Підтвердження введених даних](images/start-entry-confirmation.png)
### Як працює вся ця "магія" <a name="magic-explained"></a>
### Як працює вся ця «магія» <a name="magic-explained"></a>
Ви, більш за все, ставите питанням про те, як все ж ця HTML форма працює насправді і яким чином.
Весь процес може здатися трохи магічним: те як зображаються підписи до полів, помилки перевірки даних при некоректному
заповненні і те що все це відбувається без перезавантаження сторінки.
Ви, більш за все, ставите питанням про те, як все ж ця HTML форма працює насправді і яким чином. Весь процес може здатися трохи магічним: те як зображаються підписи до полів, помилки перевірки даних при некоректному заповненні і те що все це відбувається без перезавантаження сторінки.
Так, початкова перевірка даних дійсно проходить на стороні клієнта за допомогою JavaScript, і повторно перевіряється
на стороні сервера (PHP). [[yii\widgets\ActiveForm]] достатньо продуманий, щоб взяти правила перевірки, які ви
оголосили в `EntryForm`, перетворити їх в JavaScript код і використовувати його для проведення перевірки.
На випадок, якщо в браузері буде вимкнено JavaScript валідація проходить і на стороні сервера, як показано в методі
`actionEntry()`. Це дає впевненість в тому, що дані коректні за будь-яких обставин.
Так, провірка даних дійсно проходить на стороні клієнта за допомогою JavaScript і на стороні сервера.
[[yii\widgets\ActiveForm]] достатньо продуманий, щоб взяти правила перевірки, які ви оголосили в `EntryForm`,
перетворити їх в JavaScript код і використовувати його для проведення перевірки. На випадок, якщо в браузері буде вимкнено JavaScript валідація проходить і на стороні сервера, як показано в методі `actionEntry()`. Це дає впевненість в тому, що дані коректні за любих обставин.
> Попередження: перевірка даних на стороні клієнта це зручність, яке забезпечує кращий користувальницький досвід.
Перевірка на стороні сервера завжди обов’язкова, незважаючи на клієнтську.
Підписи для полів генеруються методом `field()`, на основі імен властивостей моделі. Наприклад, підпис `Name` генерується
для властивості `name`. Ви можете модифікувати підписи наступним чином:
......@@ -184,14 +216,16 @@ http://hostname/index.php?r=site/entry
```
> Інформація: У Yii є велика кількість віджетів, які дозволяють швидко будувати складні і динамічні представлення.
Як ви дізнаєтесь пізніше, розробляти нові віджети доволі просто. Багато із представленнь можна винести у віджети, щоб використовувати це повторно в інших частинах і тим самим спростити розробку в майбутньому.
Як ви дізнаєтесь пізніше, розробляти нові віджети доволі просто. Багато із представленнь можна винести у віджети,
щоб використовувати їх повторно в інших частинах і тим самим спростити розробку в майбутньому.
Резюме <a name="summary"></a>
-----------------------------
Підсумок <a name="summary"></a>
--------
В даному розділі ви випробували кожну частину шаблона проектування MVC. Ви дізналися як створювати класи моделей для опрацювання і перевірки даних вказаних користувачем.
В даному розділі ви випробували кожну частину шаблона проектування MVC. Ви дізналися як створювати класи моделей
для опрацювання і перевірки даних вказаних користувачем.
Також, ви дізналися як отримати дані від користувача і як їх відобразити тому ж користувачу. Ця задача може займати багато часу в процесі розробки. Yii надає потужні віджети, які роблять задачу максимально простою.
Також, ви дізналися як отримати дані від користувача і як їх відобразити тому ж користувачу. Ця задача може займати
багато часу в процесі розробки. Yii надає потужні віджети, які роблять задачу максимально простою.
В наступному розділі ви дізнаєтесь як працювати з базами даних, що необхідно в більшості додатків.
Генерація коду за допомогою Gii
========================
===============================
Цей розділ описує, як використовувати [Gii](tool-gii.md) для автоматичної генерації коду, процедура якої має певні спільні риси з веб-сайтом. Використання Gii для автоматичного створення коду є простою процедурою введення правильної інформації згідно інструкцій, які містяться на
Gii.
Цей розділ описує, як використовувати [Gii](tool-gii.md) для автоматичної генерації коду, процедура якої має певні
спільні риси з веб-сайтом. Використання Gii для автоматичного створення коду є простою процедурою введення
правильної інформації згідно інструкцій, які містяться на Gii.
В даному керівництві ви дізнаєтесь:
* Включити Gii у вашому додатку
* Використання Gii для генерації Active Record класів
* Увімкнути Gii у вашому додатку
* Використання Gii для генерації класів Active Record
* Використання Gii для генерації коду по операціям CRUD бази даних
* Налаштування коду, що був згенерований Gii
Підготовка Gii <a name="starting-gii"></a>
------------
--------------
[Gii](tool-gii.md) надається як [модуль](structure-modules.md). Ви можете підключити Gii налаштувавши його модуль [[yii\base\Application::modules|modules]] в налаштуваннях додатка. В залежності від налаштувань вашого додатка, ви можете знайти наступний код в конфігураційному файлі `config/web.php`:
[Gii](tool-gii.md) надається як [модуль](structure-modules.md). Ви можете підключити модуль Gii, налаштувавши відповідну
властивість [[yii\base\Application::modules|modules]] в налаштуваннях додатка. В залежності від налаштувань вашого додатка,
ви можете знайти наступний код в конфігураційному файлі `config/web.php`:
```php
$config = [ ... ];
......@@ -26,64 +29,87 @@ if (YII_ENV_DEV) {
}
```
Наведена вище конфігурація підключає модуль `gii` в тому випадку, коли ваш додаток знаходиться в [середовищі розробки](concept-configurations.md#environment-constants) і наслідує клас [[yii\gii\Module]].
Наведена вище конфігурація підключає модуль `gii` у тому випадку, коли ваш додаток знаходиться в
[середовищі розробки](concept-configurations.md#environment-constants) і наслідує клас [[yii\gii\Module]].
Якщо ви перевірите [вхідний скрипт](structure-entry-scripts.md) `web/index.php` вашого додатку, то знайдете наступний рядок `YII_ENV_DEV`, який переводить додаток в середовище розробки.
Якщо ви перевірите [вхідний скрипт](structure-entry-scripts.md) `web/index.php` вашого додатку, то знайдете наступний
рядок `YII_ENV_DEV`, який переводить додаток в середовище розробки.
```php
defined('YII_ENV') or define('YII_ENV', 'dev');
```
Завдяки даному рядку, ваш додаток знаходиться в режимі розробки, і буде підключати Gii, із вищевказаною конфігурацією. Тепер ви можете отримати доступ до Gii за наступною адресою:
Завдяки даному рядку, ваш додаток знаходиться в режимі розробки, і буде підключати Gii, із вищевказаною конфігурацією.
Тепер ви можете отримати доступ до Gii за наступною адресою:
```
http://hostname/index.php?r=gii
```
![Gii](../guide/images/start-gii.png)
> Примітка: Якщо ви звертаєтеся до Gii від машини, крім локальної, доступ буде заборонений за замовчуванням із міркувань
безпеки. Ви можете налаштувати Gii, додавши дозволені IP адреси, як показано нижче,
>
```php
'gii' => [
'class' => 'yii\gii\Module',
'allowedIPs' => ['127.0.0.1', '::1', '192.168.0.*', '192.168.178.20'] // налаштувати для ваших потреб
],
```
![Gii](images/start-gii.png)
Генерація класу Active Record <a name="generating-ar"></a>
---------------------------------
-----------------------------
Використовуючи Gii для генерації класу Active Record, виберіть "Model Generator" (натиснувши на посилання на сторінці Gii). Далі заповніть форму наступними даними:
Використовуючи Gii для генерації класу Active Record, виберіть "Model Generator" (натиснувши на посилання на сторінці Gii).
Далі заповніть форму наступними даними:
* Ім’я таблиці: `country`
* Клас моделі: `Country`
![Герератор моделі](../guide/images/start-gii-model.png)
![Генератор моделі](images/start-gii-model.png)
Далі, натисніть на кнопку "Перегляду". Ви побачите файл `models/Country.php` який буде створений в результаті даних дій. Ви можете натиснути на ім'я файлу класу для перегляду його вмісту.
Далі, натисніть на кнопку "Перегляду" ("Preview"). Ви побачите файл `models/Country.php`, який буде створено в результаті
даних дій. Ви можете натиснути на ім’я файлу класу для перегляду його вмісту.
Якщо при використанні Gii, раніше вже був створений файл моделі, то він буде перезаписаний. Для того, щоб переглянути відмінності в коді натисніть на кнопку `diff` поруч з ім'ям файлу.
Якщо при використанні Gii, раніше вже був створений файл моделі, то він буде перезаписаний. Для того, щоб переглянути
відмінності в коді натисніть на кнопку `diff` поруч з ім’ям файлу.
![Прев'ю генератора моделі](../guide/images/start-gii-model-preview.png)
![Прев’ю генератора моделі](images/start-gii-model-preview.png)
При перезаписі існуючого файлу, встановіть прапорець поруч із чекбоксом "перезаписати", а потім натисніть кнопку "Створити". При створенні нового файлу, ви можете просто натиснути на кнопку "Створити".
При перезаписі існуючого файлу, встановіть прапорець поруч із чекбоксом "перезаписати" ("overwrite"), а потім натисніть
кнопку "Створити" ("Generate"). При створенні нового файлу, ви можете просто натиснути на кнопку "Створити" ("Generate").
Далі, ви побачите сторінку підтвердження із відображенням коду, який був сгенерований. Якщо ви перезаписували вже існуючий файл, то побачите повідомлення про те, що він був переписаний і замінений на щойно згенерований код.
Далі, ви побачите сторінку підтвердження із відображенням коду, який був сгенерований. Якщо ви перезаписували вже існуючий
файл, то побачите повідомлення про те, що він був переписаний і замінений на щойно згенерований код.
Генерація коду CRUD <a name="generating-crud"></a>
--------------------
-------------------
CRUD розшифровується як Створити, Прочитати, Оновити, і Видалити, це операції що вирішують чотири спільні завдання з маніпулюванням даними на більшості веб-сайтів. Щоб створити CRUD інтерфейс використовуючи Gii, виберіть "CRUD Generator" (натиснувши відповідну кнопку на сторінці Gii). Наприклад, для таблиці "country", заповніть наступні поля форми:
CRUD розшифровується як Створити, Прочитати, Оновити, і Видалити, це операції що вирішують чотири спільні завдання
з маніпулюванням даними на більшості веб-сайтів. Щоб створити CRUD інтерфейс використовуючи Gii, оберіть
"CRUD Generator" (натиснувши відповідну кнопку на сторінці Gii). Наприклад, для таблиці "country", заповніть наступні поля форми:
* Клас моделі: `app\models\Country`
* Клас моделі пошуку: `app\models\CountrySearch`
* Клас контролера: `app\controllers\CountryController`
![CRUD генератор](../guide/images/start-gii-crud.png)
![CRUD генератор](images/start-gii-crud.png)
Далі, натисніть на кнопку "Перегляду". Ви побачите файл `models/Country.php` який буде створений в результаті даних дій. Ви можете натиснути на ім'я файлу класу для перегляду його вмісту.
Далі, натисніть на кнопку "Перегляду" ("Preview"). Ви побачите файл `models/Country.php` який буде створений в
результаті даних дій. Ви можете натиснути на ім’я файлу класу для перегляду його вмісту.
[[NEED THE IMAGE HERE]]
![Прев’ю CRUD генератор](images/start-gii-crud-preview.png)
Якщо ви попередньо створили контролер `controllers/CountryController.php` і файл предствлення `views/country/index.php` (в розділі "Робота з базами даних" даного посібника), виберіть чекбокс "перезаписати" і замініть їх. (Попередні версії файлів на мають повного CRUD функціоналу.)
Якщо ви попередньо створили контролер `controllers/CountryController.php` і файл представлення `views/country/index.php`
(в розділі "Робота з базами даних" даного посібника), оберіть чекбокс "перезаписати" і замініть їх.
(Попередні версії файлів на мають повного CRUD функціоналу.)
Спробуєм <a name="trying-it-out"></a>
-------------
Спробуємо <a name="trying-it-out"></a>
---------
Щоб побачити все, що було створено під час роботи, відкрийте в браузері наступний URL:
......@@ -91,24 +117,30 @@ CRUD розшифровується як Створити, Прочитати,
http://hostname/index.php?r=country/index
```
Ви побачите таблицю даних, що показує країни з таблиці бази даних. Ви зможете відсортувати сітку, або відфільтрувати пошук, вказавши умови фільтрації в заголовках стовпців.
Ви побачите таблицю даних, що показує країни з таблиці бази даних. Ви зможете відсортувати сітку, або відфільтрувати
пошук, вказавши умови фільтрації в заголовках стовпців.
Для кожної країни, що відображаються в таблиці, ви можете використати функції перегляду деталей, оновлення даних, або взагалі видалити її. Ви також можете натиснути на кнопку "Створити країну" зверху сітки відображення, яка переадресує вас на форму створення нової країни.
Для кожної країни, що відображається в таблиці, ви можете використати функції перегляду деталей, оновлення даних, або
взагалі видалити її. Ви також можете натиснути на кнопку "Створити країну" зверху сітки відображення, яка переадресує
вас на форму створення нової країни.
![Сітка даних країн](../guide/images/start-gii-country-grid.png)
![Сітка даних країн](images/start-gii-country-grid.png)
![Оновлення даних країни](../guide/images/start-gii-country-update.png)
![Оновлення даних країни](images/start-gii-country-update.png)
Нижче представлений список файлів, згенерованих Gii, в тому разі, якщо ви захочете дослідити, як реалізовані ці можливості, або доналаштувати їх під свої потреби:
Нижче наведено перелік файлів, згенерованих Gii, у тому разі, якщо ви захочете дослідити, як реалізовані ці можливості,
або доналаштувати їх під свої потреби:
* Контролер: `controllers/CountryController.php`
* Моделі: `models/Country.php` і `models/CountrySearch.php`
* Представлення: `views/country/*.php`
> Інформація: Gii це гнучкий і розширюваний інструмент для генерації коду. При правильному використувані, від дозволить вам значно прискорити розробку ваших додатків. Для більш докладної інформації, будьласка, зверніться до розділу [Gii](tool-gii.md).
> Інформація: Gii це гнучкий і розширюваний інструмент для генерації коду. При правильному використувані, від дозволить
вам значно прискорити розробку ваших додатків. Для більш докладної інформації, будьласка, зверніться до розділу [Gii](tool-gii.md).
Резюме <a name="summary"></a>
-------
Підсумок <a name="summary"></a>
--------
В цьому розділі ви дізналися, як використовуючи Gii генерувати код, який реалізує повну функціональність CRUD для маніпулювання даними що зберігаються в таблицях баз даних.
В цьому розділі ви дізналися як, використовуючи Gii, генерувати код, який реалізує повну функціональність CRUD для
маніпулювання даними, що зберігаються в таблицях баз даних.
Говоримо «Привіт»
================
=================
В даному розділі розглянемо як створити нову сторінку з надписом «Привіт». В процесі вирішеня задачі ви створите
[подію контролера](structure-controllers.md) і [представлення](structure-views.md):
[дію контролера](structure-controllers.md) і [представлення](structure-views.md):
* Додаток опрацює запит і передасть управління відповідній події;
* Подія, в свою чергу, відобразить представлення з надписом "Привіт" кінцевому користувачу.
* Додаток опрацює запит і передасть управління відповідній дії
* Дія, в свою чергу, відобразить представлення з надписом "Привіт" кінцевому користувачу
З допомогою даного керівництва ви вивчите
З допомогою даного керівництва ви вивчите:
* Як створити [подію](structure-controllers.md), яка буде відповідати на запити;
* Як створити [представлення](structure-views.md), щоб формувати зміст відповіді;
* Як додаток відправляє запити до [події](structure-controllers.md).
1. Як створити [дію](structure-controllers.md), яка буде відповідати на запити
2. Як створити [представлення](structure-views.md), щоб формувати зміст відповіді
3. Як додаток відправляє запити до [дії](structure-controllers.md).
Створення Події <a name="creating-action"></a>
------------------------------------------------
Створення дії <a name="creating-action"></a>
-------------
Для нашої задачі знадобиться [подія](structure-controllers.md) `say`, котра читає параметр `message` із
запиту і відображає його значення користувачу. Якщо в запиті відсутній параметр `message`, то подія буде відображати «Привіт».
Для нашої задачі знадобиться [дія](structure-controllers.md#creating-actions) `say`, котра читає параметр `message` із
запиту і відображає його значення користувачу. Якщо в запиті відсутній параметр `message`, то дія буде відображати «Привіт».
> Інформація: [Події](structure-controllers.md) можуть бути запущені безпосередньо користувачем і згруповані в
[контролери](structure-controllers.md). Результатом виконання події є відповідь, яку отримує користувач.
> Інформація: [Дії](structure-controllers.md#creating-actions) можуть бути запущені безпосередньо користувачем і
згруповані в [контролери](structure-controllers.md). Результатом виконання дії є відповідь, яку отримує користувач.
Події оголошуються в [контролерах](structure-controllers.md). Для зручності, ви можете оголосити подію
Дії оголошуються в [контролерах](structure-controllers.md). Для зручності, ви можете оголосити дію
`say` в уже існуючому контролері `SiteController`, який оголошений у файлі класа `controllers/SiteController.php`:
```php
......@@ -44,26 +44,34 @@ class SiteController extends Controller
}
```
В наведеному коді подія `say` оголошена як метод `actionSay` в класі `SiteController`.
Yii використовує префікс `action` для того, щоб відрізняти методи-події і звичайні методи. Назва після префікса `action`
вважається ідентифікатором відповідної події.
> Інформація: Ідентифікатори подій задаються в нижньому регістрі. Якщо ідентифікатор складається з декількох слів, вони
з’єднуються дефісами, тобто `create-comment`. Імена методів подій отримуються шляхом видалення дефісів з ідентифікатора, перетворення першої літери кожного слова у верхній регістр і добавлення префікса `action`.
Наприклад, ідентифікатор події `create-comment` відповідає методу `actionCreateComment`.
В наведеному коді дія `say` оголошена як метод `actionSay` в класі `SiteController`.
Yii використовує префікс `action` для того, щоб відрізняти методи-дії і звичайні методи. Назва після префікса `action`
вважається ідентифікатором відповідної дії.
Метод події приймає параметр `$message`, який за замовчуванням дорівнює `"Привіт"`. Коли додаток отримує запит і визначає, що подія `say` відповідає за його опрацювання, параметр наповнюється одноіменним значенням із запиту.
Коли черга доходить до іменування дій, слід розуміти як Yii відноситься до ідентифікаторів дій.
Ідентифікатори дій задаються в нижньому регістрі. Якщо ідентифікатор складається з декількох слів, вони
з’єднуються дефісами, тобто `create-comment`. Імена методів дій отримуються шляхом видалення дефісів з ідентифікатора,
перетворення першої літери кожного слова у верхній регістр і додавання префікса `action`.
Наприклад, ідентифікатор дії `create-comment` відповідає методу `actionCreateComment`.
Всередені метода події, для відображення [представлення](structure-views.md) з ім’ям `say`, використовується метод
Метод дії приймає параметр `$message`, який за замовчуванням дорівнює `"Привіт"` (так само, як ви звикли визначати
значення за замовчуванням для аргументів методу у PHP). Коли додаток отримує запит і визначає,
що дія `say` відповідає за його опрацювання, параметр наповнюється одноіменним значенням із запиту.
Іншими словами, якщо запит містить параметр `message` із значенням `"До побачення"`, то змінній `$message`
всередині дії буде призначено це значення.
Всередені метода дії, для відображення [представлення](structure-views.md) з ім’ям `say`, використовується метод
[[yii\web\Controller::render()|render()]]. Для того, щоб вивести повідомлення, у представлення передається параметр `message`.
Результат відображення з допомогою `return` передається додатку, котрий віддає його користувачу.
Створення представлення <a name="creating-view"></a>
---------------------------------------------------
-----------------------
[Представлення](structure-views.md) є скриптами, які використовуються для формування тіла відповіді. Для нашого
додатку ви створите представлення `say`, яке буде виводити параметр `message`, отриманий із метода події:
додатку ви створите представлення `say`, яке буде виводити параметр `message`, отриманий із метода дії:
```php
<?php
......@@ -73,11 +81,11 @@ use yii\helpers\Html;
```
Представлення `say` мусить бути збережено у файлі `views/site/say.php`. Коли метод [[yii\web\Controller::render()|render()]]
викликається в події, він буде шукати PHP файл з ім’ям виду `views/ControllerID/ActionID/ViewName.php`.
викликається в дії, він буде шукати PHP файл з ім’ям виду `views/ControllerID/ActionID/ViewName.php`.
Варто замітити, що в коді вище параметр `message` [[yii\helpers\Html::encode()|екранується для HTML]] перед відображенням.
Це обов’язково так як параметр приходить від користувача, котрий може спробувати провести
[XSS атаку](http://uk.wikipedia.org/wiki/%D0%9C%D1%96%D0%B6%D1%81%D0%B0%D0%B9%D1%82%D0%BE%D0%B2%D0%B8%D0%B9_%D1%81%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D1%96%D0%BD%D0%B3)
Варто відмітити, що в коді вище параметр `message` [[yii\helpers\Html::encode()|екранується для HTML]] перед відображенням.
Це обов’язково, так як параметр приходить від користувача, котрий може спробувати провести
[XSS атаку](http://uk.wikipedia.org/wiki/%D0%9C%D1%96%D0%B6%D1%81%D0%B0%D0%B9%D1%82%D0%BE%D0%B2%D0%B8%D0%B9_%D1%81%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D1%96%D0%BD%D0%B3),
шляхом вставки небезпечного JavaScript кода.
Ви можете доповнити представлення `say` HTML тегами, текстом або кодом PHP. Фактично, представлення `say` є
......@@ -85,43 +93,47 @@ use yii\helpers\Html;
скриптом представлення, буде передано додатком користувачу.
Спробуєм <a name="trying-it-out"></a>
--------------------------------------
Спробуємо <a name="trying-it-out"></a>
---------
Після створення події і представлення ви можете перейти на нову сторінку по наступному URL:
Після створення дії і представлення, ви можете перейти на нову сторінку по наступному URL:
```
http://hostname/index.php?r=site/say&message=Привіт+світ
```
![Привіт, світ](../guide/images/start-hello-world.png)
![Привіт, світ](images/start-hello-world.png)
Буде відображена сторінка з надписом "Привіт світ". Вона використовує ту ж шапку і футер, що і решта сторінок додатка.
Буде відображена сторінка з надписом Привіт світ. Вона використовує ту ж шапку і футер, що і решта сторінок додатка.
Якщо ви не вкажете параметр `message`, то побичите на сторінці лише «Привіт». Це відбувається тому, що `message` передається
в метод `actionSay()` і значення за замовчуванням — «Привіт».
> Інформація: Нова сторінка використовує ту ж шапку і футер, що і решта сторінок, тому що метод
[[yii\web\Controller::render()|render()]] автоматично підставляється в результат представлення `say` в, так називаємий,
[макет](structure-views.md) `views/layouts/main.php`.
Параметр `render` потребує додаткових пояснень. Він пов’язаний з [маршрутом (route)](runtime-routing.md), який являє собою унікальний ідентифікатор, який вказує на подію. Його формат `ControllerID/ActionID`. Коли додаток отримує запит, він перевіряє параметр `render` і, використовуючи `ControllerID`, визначає який контролер слід використовувати для опрацювання запиту. Потім, контролер використовує частину `ActionID`, щоб визначити яка подія виконує реальну роботу.
В нашому випадку маршрут `site/say` буде відповідати контролеру `SiteController` і його події `say`.
В результаті, для відпрацювання запиту буде визваний метод `SiteController::actionSay()`.
> Інформація: Як і події, контролери також мають ідентифікатори, котрі однозначно визначають їх в додатку.
Ідентифікатори контролерів використовують ті ж самі правила, що і ідентифікатори подій. Імена класів
контролерів отримуються шляхом видалення дефісів з ідентифікатора, перетворення першої літери кожного слова у верхній регістр і додавання в кінець `Controller`. Наприклад, ідентифікатор контролера `post-comment` відповідає
[[yii\web\Controller::render()|render()]] автоматично підставляється в результат представлення `say` в, так званий,
[макет](structure-views.md#layouts) `views/layouts/main.php`.
Параметр `r` потребує додаткових пояснень. Він пов’язаний з [маршрутом (route)](runtime-routing.md), який являє
собою унікальний ідентифікатор, який вказує на дію. Його формат `ControllerID/ActionID`. Коли додаток отримує запит,
він перевіряє цей параметр і, використовуючи `ControllerID`, визначає який контролер слід використовувати для
опрацювання запиту. Потім, контролер використовує частину `ActionID`, щоб визначити яка дія виконує реальну роботу.
В нашому випадку маршрут `site/say` буде відповідати контролеру `SiteController` і його дії `say`.
В результаті, для відпрацювання запиту буде викликано метод `SiteController::actionSay()`.
> Інформація: Як і дії, контролери також мають ідентифікатори, котрі однозначно визначають їх в додатку.
Ідентифікатори контролерів використовують ті ж самі правила, що і ідентифікатори дій. Імена класів
контролерів отримуються шляхом видалення дефісів з ідентифікатора, перетворення першої літери кожного слова у верхній
регістр і додавання в кінець `Controller`. Наприклад, ідентифікатор контролера `post-comment` відповідає
імені класа контролера `PostCommentController`.
Резюме <a name="summary"></a>
-----------------------------
Підсумок <a name="summary"></a>
--------
В даному розділі ви затронули тему контролерів і представленнь в паттерні MVC. Ви створили подію як частину контролера,
В даному розділі ви торкнулися теми контролерів і представлень в паттерні MVC. Ви створили дію, як частину контролера,
який опрацьовує запити, і представлення, яке приймає участь у формувані відповіді. В цьому процесі ніяк не була задіяна
модель, так як в ролі даних виступає тільки простий параметр `message`.
Також ви ознайомились із концепцією маршрутизації, котра є сполучною ланкою між запитом користувача і подією контролера.
Також ви ознайомились із концепцією маршрутизації, котра є сполучною ланкою між запитом користувача і дією контролера.
В наступному розділі ви дізнаєтесь як створювати моделі і добавляти нові сторінки з HTML формами.
Встановлення Yii
==============
================
Ви можете встановити Yii двома шляхами: використовуючи [Composer](http://getcomposer.org/) або завантаживши архів.
Перший варіант бажаніший тому, що дозволить встановити всі нові [розширення](structure-extensions.md)
......@@ -7,7 +7,7 @@
Встановлення за допомогою Composer <a name="installing-via-composer"></a>
-----------------------
----------------------------------
Якщо Composer все ще не встановлено, то це можна зробити за допомогою інструкції на [getcomposer.org](https://getcomposer.org/download/), або одним із перерахованих способів:
......
Що далі?
=============
Наступні кроки
==============
В підсумку, ви створили повноцінний додаток на Yii, і дізналися, як реалізувати деякі, найбільш часто використовувані функції, такі як отримання даних від користувача за допомогою HTML форм, виборці даних з баз даних і відображення їх в розподіленому вигляді на сторінці.
Також, ви дізналися, як використовувати [Gii](tool-gii.md) для автоматичної генерації коду, що перетворює программування в настільки просту задачу, як заповнити деякі форми.
В даному розділі ми підіб’ємо підсумки по пройденим ресурсам Yii, які допоможуть вам у більш продуктивному використані Yii.
Якщо ви прочитали весь розділ "Приступаючи до роботи", то, напевне, ви створили повноцінний додаток Yii. У процесі ви дізналися,
як реалізувати деякі найбільш часто використовувані функції, таких, як отримання даних від користувачів за допомогою HTML-форми,
вибірка даних з бази даних і відображення даних із розбиттям по сторінкам. Також ви дізналися, як використовувати
[Gii](tool-gii.md) для автоматичної генерації коду, що перетворює більшу частину процесу веб-розробки у завдання настільке просте,
як заповнення деяких форм.
* Документація
- Докладний посібник:
Як випливає з назви, посібник точно визначає, як Yii повинен працювати і дає вам загальні вказівки по його використанню.
Це самий важливий Yii підручник, з яким ви мусити ознайомитись, перш ніж писати різноманітний Yii код.
- Опис класів:
- [Докладний Посібник](http://www.yiiframework.com/doc-2.0/guide-README.html):
Як випливає з назви, посібник точно визначає, як Yii повинен працювати і дає вам загальні вказівки щодо його застосування.
Це найважливіший Yii підручник, з яким ви маєте ознайомитись, перш ніж писати Yii код.
- [Опис класів](http://www.yiiframework.com/doc-2.0/index.html):
Визначає використання кожного класу, представленого в Yii.
Їм слід користуватися, коли ви пишете код і хочете розібратися у використанні конкретного класу, методу, властивості.
- Вікі статті:
Вікі статті, написані користувачами Yii на основі їх власного досвіду.
Опис класів найкраще використовувати після контекстного розуміння всього фреймворка.
- [Wiki статті](http://www.yiiframework.com/wiki/?tag=yii2):
Wiki статті написані користувачами Yii на основі їх власного досвіду.
Більшість з них написані як рецепти з куховарської книги, які показують, як вирішити конкретні проблеми з використанням Yii.
Причому якість цих статей може бути такоюж ж гарною, як Детальний посібник.
Вони корисні тим, що охоплюють тему ширше і часто можуть надати вам готові рішення для подальшого використання.
- Книги
Варто зауважити, що якість даних статей може бути не такою гарною, як у Докладному Посібнику, але вони корисні тим,
що вони охоплюють ширші теми і часто можуть забезпечити готові рішення для подальшого використання.
- [Книги](http://www.yiiframework.com/doc/)
* [Розширення](http://www.yiiframework.com/extensions/):
Yii пишається бібліотекою із тисяч внесених користувачами розширень,
   які можуть бути легко підключені у ваші додатки та зробити розробку додатків ще швидшим і простішим.
Yii пишається бібліотекою із тисяч розширень, внесених користувачами, які можуть бути легко підключені у ваші додатки та зробити розробку додатків ще швидшим і простішим.
* Спільнота
- [Форум](http://www.yiiframework.com/forum/)
- [GitHub](https://github.com/yiisoft/yii2)
- [Facebook](https://www.facebook.com/groups/yiitalk/)
- [Twitter](https://twitter.com/yiiframework)
- [LinkedIn](https://www.linkedin.com/groups/yii-framework-1483367)
\ No newline at end of file
- Форум: <http://www.yiiframework.com/forum/>
- IRC chat: The #yii channel on the freenode network (<irc://irc.freenode.net/yii>)
- GitHub: <https://github.com/yiisoft/yii2>
- Facebook: <https://www.facebook.com/groups/yiitalk/>
- Twitter: <https://twitter.com/yiiframework>
- LinkedIn: <https://www.linkedin.com/groups/yii-framework-1483367>
Запуск додатка
====================
==============
Після встановлення Yii, базовий додаток буде доступний або по URL `http://hostname/basic/web/index.php`, або по `http://hostname/index.php`, в залежності від налаштування Web сервера. Даний розділ - загальне введення в організацію коду, вбудований функціонал і опрацювання звернень додатком Yii.
Після встановлення Yii, базовий додаток буде доступний або по URL `http://hostname/basic/web/index.php`,
або по `http://hostname/index.php`, в залежності від налаштування Web сервера. Даний розділ - загальне введення в
організацію коду, вбудований функціонал і опрацювання запитів додатком Yii.
> Інформація: Для спрощення, далі в даному посібнику передбачається, що Yii встановлений в директорію `basic/web`,
яка, в свою чергу, встановлена, як коренева директорія в налаштуваннях Web сервера. В результаті, звернувшись до URL
`http://hostname/index.php` ви отримаєте доступ до додатку. Відрегулюйте URL-адреси для ваших потреб.
> Інформація: Далі, в даному посібнику передбачається що Yii встановлений в теку `basic/web`, яка, в свою чергу, встановлена як коренева директорія в налаштуваннях Web сервера. В результаті, звернувшись по URL `http://hostname/index.php` ви отримаєте доступ до додатку, розміщенному в `basic/web`. Детальніше з процесом початкового налаштування можна ознайомитись в розділі [Встановлення Yii](start-installation.md).
Функціонал <a name="functionality"></a>
---------------
----------
Вбудований шаблон простого додатку складається з чотирьох сторінок:
* домашня сторінка, відображається при переході по URL `http://hostname/index.php`
* "About" ("Про нас")
* на сторінці "Contact" знаходиться форма зворотнього зв’язку, на якій користувач може звернутися до розробника по e-mail
* на сторінці "Login" відображається форма авторизації. Спробуйте авторизуватись з логіном/паролем "admin/admin". Зверніть увагу на зміну розділу "Login" в головному меню на "Logout".
* на сторінці "Login" відображається форма авторизації. Спробуйте авторизуватись з логіном/паролем "admin/admin".
Зверніть увагу на зміну розділу "Login" в головному меню на "Logout".
Ці сторінки використовують суміжний хедер (шапка сайта) і футер (підвал). В "шапці" знаходиться головне меню, за допомогою якого користувач переміщається по сайту. В "підвалі" - копірайт і загальна інформація.
Ці сторінки використовують спільний хедер (шапка сайта) і футер (підвал). В "шапці" знаходиться головне меню, за
допомогою якого користувач переміщається по сайту.
В самій верхній частині вікна ви будете бачити системні повідомлення Yii - журнал, відлагоджувальну інформацію, повідомлення про помилки, запити до бази даних і т.п. Відображенням данної інформацію керує [вбудований відладчик](tool-debugger.md), він записує і відображає інформацію про хід виконання додатку.
У нижній частині вікна ви зможете бачити системні повідомлення Yii - журнал, відлагоджувальну інформацію,
повідомлення про помилки, запити до бази даних і т.п. Відображенням данної інформацію керує
[вбудований відладчик](tool-debugger.md), він записує і відображає інформацію про хід виконання додатку.
Структура додатка Yii <a name="application-structure"></a>
---------------------
Нижще наведений перелік основних директорій і файлів вашого додатку (вважаєм, що додаток встановлений в директорію `basic`):
Нижче наведений перелік основних директорій і файлів вашого додатку (вважаємо, що додаток встановлений в директорію `basic`):
```
basic/ кореневий каталог додатка
......@@ -43,36 +52,39 @@ basic/ кореневий каталог додатка
yii скрипт виконання консольного додатку Yii
```
В цілому, додаток Yii можна розділити на дві категорії файлів: розміщенні в `basic/web` і розміщенні в інших директоріях. Перша категорія доступна через Web (наприклад, браузером), друга недоступна зовні та і не повинна бути так як містить службову інформацію.
В цілому, додаток Yii можна розділити на дві категорії файлів: розміщенні в `basic/web` і розміщенні в інших директоріях.
Перша категорія доступна через HTTP (наприклад, браузером), друга недоступна зовні, та і не повинна бути, так як містить службову інформацію.
В Yii реалізована схема проектування [модель-представлення-контролер (MVC)](http://http://uk.wikipedia.org/wiki/Model-View-Controller),
яка відповідає структурі директорій додатка. В директорії `models` знаходяться [Моделі](structure-models.md),
в `views` розміщені [Представлення](structure-views.md), а в каталозі `controllers` всі [Контролери](structure-controllers.md) додатка.
яка відповідає структурі директорій додатка. В директорії `models` знаходяться класи [моделей](structure-models.md),
в `views` розміщені скрипти [представлень](structure-views.md), а в каталозі `controllers` всі класи [контролерів](structure-controllers.md) додатка.
Діаграма нижче демонструє внутрішню будову додатка.
Діаграма нижче демонструє статичну структуру додатка.
![внутрішня будова додатка](../guide/images/application-structure.png)
![Статична структура додатка](images/application-structure.png)
В кожному додатку Yii є місце входження в додаток, `web/index.php` це єдиний PHP-скрипт доступний для виконання через Web. Він отримує вхідний запит і створює екземпляр [додатку](structure-applications.md).
[Додаток](structure-applications.md) опрацьовує вхідні запити з допомогою [компонентів](concept-components.md) і відправляє запит контролеру. [Віджети](structure-widgets.md) використовуються у [Представленнях](structure-views.md) для побудови динамічних інтерфейсів сайта.
В кожному додатку Yii є місце входження в додаток, `web/index.php` - це єдиний PHP-скрипт доступний для виконання через Web.
Він отримує вхідний запит і створює екземпляр [додатку](structure-applications.md). [Додаток](structure-applications.md)
опрацьовує вхідні запити з допомогою [компонентів](concept-components.md) і відправляє запит контролеру.
[Віджети](structure-widgets.md) використовуються у [представленнях](structure-views.md) для побудови динамічних інтерфейсів сайта.
Життєвий цикл запиту користувача <a name="request-lifecycle"></a>
-----------------
Життєвий цикл запиту <a name="request-lifecycle"></a>
--------------------
На діаграмі показано як додаток опрацьовує запит.
На діаграмі показано, як додаток відпрацьовує запит.
![Життєвий цикл запиту](../guide/images/request-lifecycle.png)
![Життєвий цикл запиту](images/request-lifecycle.png)
1. Користувач звертається до [місця входження](structure-entry-scripts.md) `web/index.php`.
2. Скрипт завантажує конфігурацію [configuration](concept-configurations.md) і створює екземпляр [додатку](structure-applications.md) для наступного опрацювання запиту.
3. Додаток визначає [маршрут](runtime-routing.md) запиту за допомогою компонента додатка [запит](runtime-requests.md).
1. Користувач робить запит до [місця входження](structure-entry-scripts.md) `web/index.php`.
2. Скрипт завантажує конфігурацію [configuration](concept-configurations.md) і створює екземпляр
[додатку](structure-applications.md) для наступного опрацювання запиту.
3. Додаток визначає [маршрут](runtime-routing.md) запиту за допомогою компонента [запиту](runtime-requests.md) додатка.
4. Додаток створює екземпляр [контролера](structure-controllers.md) для виконання запиту.
5. Контролер, в свою чергу, створює [подію](structure-controllers.md) і накладає на неї фільтри.
5. Контролер, в свою чергу, створює [дію](structure-controllers.md) і накладає на неї фільтри.
6. Якщо хоч один фільтр поверне помилку - виконання додатку зупиняється.
7. Якщо всі фільтри пройдені - додаток виконується.
8. Подія завантажує модель даних. Скоріше за все із бази даних.
9. Подія генерує представлення, відображаючи в ньому дані (в т.ч. і отримані із моделі).
10. Згенерований вид додатку передається як компонент [відповідь](runtime-responses.md).
11. Компонент "відповідь" відправляє готовий результат роботи додатку браузеру користувача.
8. Дія завантажує модель даних. Скоріше за все із бази даних.
9. Дія генерує представлення, відображаючи в ньому дані (в т.ч. і отримані із моделі).
10. Згенерований вид додатку передається як компонент [відповіді](runtime-responses.md).
11. Компонент "відповіді" відправляє готовий результат роботи додатку браузеру користувача.
......@@ -27,6 +27,7 @@ Yii Framework 2 Change Log
- Bug #5863: Selecting all individual `yii\grid\CheckboxColumn` checkboxes in grid view wasn't resulting in "all" checkbox selected (samdark)
- Bug #5893: `yii\helpers\ArrayHelper::toArray()` now applies `$properties` parameter for converting descending objects in recursive calls (otsec)
- Bug #5925: `ArrayHelper::htmlEncode()` does not work properly when the value being encoded is a nested array (tebazil)
- Bug #5962: DateValidator was throwing a warning on invalid dates using the ICU format on Windows, Yii now works around this [PHP Bug](https://bugs.php.net/bug.php?id=68528) (cebe)
- Bug #5997: The same message may be exported twice to log targets (klimov-paul)
- Bug #6018: When setting the `encode` option via `yii\widgets\ActiveRecord::errorOptions`, it works the other way around (stanishevsky, qiangxue)
- Bug #6049: `yii\db\Connection::getSchema()` for Oracle should return false when the table does not exist. Oracle does not support `ON UPDATE` clause. (wenbin1989)
......
......@@ -634,7 +634,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
* or [[beforeSave()]] stops the updating process.
* @throws StaleObjectException if [[optimisticLock|optimistic locking]] is enabled and the data
* being updated is outdated.
* @throws \Exception in case update failed.
* @throws Exception in case update failed.
*/
public function update($runValidation = true, $attributeNames = null)
{
......@@ -772,7 +772,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
* Note that it is possible the number of rows deleted is 0, even though the deletion execution is successful.
* @throws StaleObjectException if [[optimisticLock|optimistic locking]] is enabled and the data
* being deleted is outdated.
* @throws \Exception in case delete failed.
* @throws Exception in case delete failed.
*/
public function delete()
{
......
......@@ -136,7 +136,10 @@ class DateValidator extends Validator
}
// enable strict parsing to avoid getting invalid date values
$formatter->setLenient(false);
return $formatter->parse($value);
// There should not be a warning thrown by parse() but this seems to be the case on windows so we suppress it here
// See https://github.com/yiisoft/yii2/issues/5962 and https://bugs.php.net/bug.php?id=68528
return @$formatter->parse($value);
} else {
// fallback to PHP if intl is not installed
$format = FormatConverter::convertDateIcuToPhp($format, 'date');
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment