lunes, 2 de marzo de 2015

Generador de Consultas (Query Builder)

Si bien podemos acceder a nuestra base de datos a través de la capa básica proporcionada por Yii (DAO), en ocasiones puede ser algo tedioso y por ende susceptible de errores al escribir nuestra consulta directamente. Una alternativa es utilizar el Generador de Consultas.

Un ejemplo sería:
$query = (new \yii\db\Query())
    ->select('id, nombre')
    ->from('usuario')
    ->limit(10);
// Crea un commando
$command $query->createCommand();
// Ejecuta el commando
$rows $command->queryAll();


Métodos de Consulta

Como se notará, yii\db\Query es la parte principal que necesitamos. Query es en realidad sólo responsable de representar diversa información de consulta. La lógica real de construcción de consultas se realiza mediante yii\db\QueryBuilder cuando se llama al método createCommand(), y la ejecución de la consulta se la realiza por medio de yii\db\Command.

Para mayor comodidad, yii\db\Query proporciona un conjunto de métodos de consulta de uso común. Por ejemplo:


  • all(): construye la consulta, lo ejecuta y devuelve todos los resultados como una matriz.
  • one(): devuelve la primera fila del resultado.
  • column(): devuelve la primera columna del resultado.
  • scalar(): devuelve la primera columna de la primera fila del resultado.
  • exists(): devuelve un valor que indica si la consulta devuelve resultados.
  • count(): devuelve el resultado de una consulta tipo COUNT. Otros métodos similares sum($q), average($q), max($q), min($q) donde $q es un parámetro obligatorio para estos métodos y puede ser el nombre de la columna o expresión.


Constructor de Consultas (Building Query)

A continuación se verá como construir diferentes cláusulas de una sentencia SQL. Por sencillez, utilizaremos $query para representar el objeto yii\db\Query.

SELECT

Debemos especificar las columnas que queremos seleccionar y la tabla de la cual obtener los datos.

$query->select('id, nombre')
    ->from('usuario');

También lo podemos hacer mediante un arreglo, lo cual es útil cuando se trata de una selección dinámica.

$query->select(['id''nombre'])
    ->from('usuario');

Consejo: Es bueno acostumbrarse a utilizar arreglos. Esto se debe a que, expresiones como CONCAT(nombre, apellido) AS nombre_completo pueden contener comas, y el resultado puede ser una cadena separada en partes por comas, y obviamente ese no es el resultado que desearíamos.

Por otro lado, podemos utilizar prefijos de tablas o alias. Una manera sería, por ejemplo
usuario.id AS usuario_id
Y si utilizamos arreglos los podemos hacer algo similares a lo siguiente:
['usuario_id' => 'usuario.id', 'usuario_nombre' => 'usuario.nombre']

A partir de la versión 2.0.1 también se pueden especificar sub-consultas como columnas. Por ejemplo:

$subQuery = (new Query)->select('COUNT(*)')->from('user');
$query = (new Query)->select(['id''count' => $subQuery])->from('post');
// $query representa la siguiente consulta SQL:
// SELECT `id`, (SELECT COUNT(*) FROM `user`) AS `count` FROM `post`

Para seleccionar filas distintas, podemos utilizar distinct como en el ejemplo siguiente:

$query->select('user_id')->distinct()->from('post');

FROM

Para especificar de cuál(es) tabla(s) obtener los datos, utilizamos from():

$query->select('*')->from('usuario');

Podemos especificar varias tablas mediante una cadena separada por comas o una matriz. Los nombres de tabla pueden contener prefijos de esquema (por ejemplo, 'public.usuario' ) y/o alias de tabla (por ejemplo, 'usuario u' ). A continuación un ejemplo:

$query->select('u.*, p.*')->from(['usuario u''post p']);

Cuando las tablas se especifican como una matriz, también se puede utilizar las claves de matriz como los alias de tabla.

$query->select('u.*, p.*')->from(['u' => 'usuario''p' => 'post']);

También es posible especificar una sub-consulta como un objeto Query.

$subQuery = (new Query())->select('id')->from('usuario')->where('estado=1');
$query->select('*')->from(['u' => $subQuery]);

WHERE

Por lo general, los datos se seleccionan cumpliendo ciertos criterios. El Generador de consultas tiene algunos métodos útiles para dichas tareas. El más poderoso de los cuales es WHERE.

La manera más sencilla de utilizarlo es con una cadena.

$query->where('estado=:estado', [':estado' => $estado]);

Cuando se utiliza cadenas, hay que tener presente que se está realizando una consulta con parámetros, no una consulta por concatenación. La manera anterior es la correcta de utilizarlo, la siguiente no lo es:

$query->where("estado=$estado"); // Incorrecto!

También se lo puede hacer a través de params addParams:

$query->where('estado=:estado');$query->addParams([':estado' => $estado]);

Condiciones múltiples también pueden utilizarse de la siguiente manera:

$query->where([
    'estado' => 10,
    'tipo' => 2,
    'id' => [4815162342],
]);

Éste código es equivalente a

WHERE (`estado` = 10) AND (`tipo` = 2) AND (`id` IN (4, 8, 15, 16, 23, 42))

Cuando necesitamos comparar un campo con el valor NULL lo hacemos de la siguiente manera:

$query->where(['estado' => null]);

con lo que obtenemos

WHERE (`estado` IS NULL)

En cambio, si necesitamos una condición del tipo NOT NULL:

$query->where(['not', ['columna' => null]]);

También es posible utilizar sub-consultas:

$userQuery = (new Query)->select('id')->from('usuario');
$query->where(['id' => $userQuery]);

lo que nos genera el código

WHERE `id` IN (SELECT `id` FROM `usuario`)

Tenemos la posibilidad de utilizar operadores. El formato de uso es [operador, término_1, término_2, ...]. Los operadores que podemos especificar son:

  • and
  • or
  • between
  • not between
  • in
  • not in
  • like
  • or like
  • not like
  • or not like
  • exists
  • not exists
  • operador matemáticos de comparación (>, <, >=, <=)


A continuación un ejemplo de cómo sería su uso.

$query->select('id')
    ->from('user')
    ->where(['>=''id'10]);

Lo que equivale a

SELECT id FROM user WHERE id >= 10;

Para construir una condición dinámicamente es conveniente utilizar andWhere() y orWhere():

$stado 10;$termino_busqueda 'yii';
$query->where(['estado' => $estado]);
if (!empty($termino_busqueda)) {
    $query->andWhere(['like''titulo'$termino_busqueda]);
}

En este caso, termino_busqueda no es vacío, por lo que la consulta generada sería:

WHERE (`estado` = 10) AND (`titulo` LIKE '%yii%')

Constructor de Condiciones Filtro

Cuando construimos condiciones para filtrar nuestros datos, basados en lo que el usuario ingresa, queremos manejar adecuadamente los campos vacíos. Por ejemplo, un usuario puede llenar un formulario en el que no todos los campos son obligatorios, por lo que los campos vacíos no queremos que los tome en cuenta. Para lograr este objetivo podemos utilizar filterWhere().

// $username y $email son ingresados por un usuario
$query->filterWhere([
    'username' => $username,
    'email' => $email,
]);

El método filterWhere() es similar a Where(). La diferencia principal es que filterWhere() remueve los valores vacíos. Se considera campos vacíos a aquellos que tienen el valor null, una cadena vacía, una cadena de espacios en blanco, o un arreglo vacío.

Se puede utilizar andFilterWhere() y orFilterWhere() para añadir más condiciones.

ORDER BY

Para ordenar los datos se puede utilizar orderBy o addOrderBy:
$query->orderBy([
    'id' => SORT_ASC,
    'nombre' => SORT_DESC,
]);

GROUP BY y HAVING

Para añadir una cláusula GROUP BY a nuestra sentencia:

$query->groupBy('id, estado');

Si queremos añadir otro campo para ser agrupado:

$query->addGroupBy(['creado_el''actualizado_el']);

Para añadir una condición HAVING:

$query->having(['estado' => $estado]);

LIMIT y OFFSET

Para limitar el resultado a 10 filas:

$query->limit(10);

Para saltar 100 filas:

$query->offset(100);

JOIN

Para la cláusula JOIN tenemos los siguiente métodos:

  • innerJoin()
  • leftJoin()
  • rightJoin()


Por ejemplo:

$query->select(['usuario.nombre AS autor''post.titulo as titulo'])
    ->from('usuario')
    ->leftJoin('post''post.usuario_id = usuario.id');

Si nuestra base de datos no soporta alguno de los tipos de JOIN, podemos utilizar el método genérico join:

$query->join('FULL OUTER JOIN''post''post.usuario_id = usuario.id');

De la misma manera que FROM, podemos utilizar sub-consultas. Por ejemplo:

$query->leftJoin(['u' => $subQuery], 'u.id=autor_id');

UNION

En Yii primero debemos construir la primera consulta, luego construir la segunda, y por último unir los resultados. Por ejemplo:

$query = new Query();$query->select("id, categoria_id as tipo, nombre")->from('post')->limit(10);
$otroQuery = new Query();
$otroQuery->select('id, tipo, nombre')->from('usuario')->limit(10);
$query->union($otroQuery);

Consulta por lotes 

Cuando se trabaja con grandes cantidades de datos, métodos como yii\db\Query::all() no son adecuados, ya que requieren la carga de todos los datos en la memoria. Para mantener el requisito de memoria baja, Yii ofrece apoyo a la consulta por lotes. Una consulta por lotes hace uso de cursores de datos y recupera los datos en lotes.

Un ejemplo es el siguiente:

use yii\db\Query;
$query = (new Query())
    ->from('usuario')
    ->orderBy('id');

foreach ($query->batch() as $usuarios) {
    // $usuarios es un arreglo de 100 o menos filas de la tabla usuario
}
// o si se desea iterar fila por fila
foreach ($query->each() as $usuario) {
    // $usuario representa una fila de datos de la tabla usuario
}

El método yii\db\Query::batch()yii\db\Query::each() retornan un objeto yii\db\BatchQueryResult que puede ser implementado por la interfaz Iterator y por lo tanto se puede utilizar con foreach. Durante la primera iteración, se realiza una consulta SQL a la base de datos. Los datos se captan por lotes en las iteraciones restantes. Por defecto, el tamaño del lote es de 100, lo que significa que 100 filas de datos están siendo extraídas en cada lote. Se puede cambiar el tamaño de lote pasándolo como primer parámetro a los métodos batch() o each().

En comparación con  yii\db\Query::all(), la consulta por lotes sólo carga 100 filas de datos a la vez en la memoria. Si procesamos los datos y luego los descartamos de inmediato, la consulta por lotes puede ayudar a reducir el uso de memoria.



También te puede interesar:
Trabajando con bases de datos
DAO - Database Access Objects (Objetos de acceso a base de datos)
Active Record (Registro Activo)

lunes, 26 de enero de 2015

DAO - Database Access Objects (Objetos de acceso a base de datos)

Si hemos trabajando con la primera versión de Yii, recordaremos que Yii provee una API orientada al acceso de bases de datos relacionales. En esta versión el concepto se mantiene, pero se lo hace de una manera diferente.

El DAO de Yii está construido sobre la base de PDO (PHP Data Objects - Objetos de datos de PHP) , y el cual provee métodos más avanzados para el acceso a la base de datos, incluyendo Query Builder (Constructor de Consultas) y Active Record (Registro Activo).

Al utilizar el DAO de Yii, solo se requiere de la consulta SQL y arreglos PHP. El resultado, es que accedemos a la base de datos de una manera eficiente.

El DAO de Yii soporta las siguientes bases de datos:

  • MySQL
  • MariaDB
  • SQLite
  • PostgreSQL
  • CUBRID: versión 9.3 o superior.
  • Oracle
  • MSSQL: versión 2008 o superior.


Creando conexiones a bases de datos

Para acceder a una base de datos, se debe conectar a ella mediante la creación de una instancia de yii\db\Connection:

$db = new yii\db\Connection([
    'dsn' => 'mysql:host=localhost;dbname=example',
    'username' => 'root',
    'password' => '',
    'charset' => 'utf8',
]);

Puesto que es muy seguro que necesitemos conectarnos a nuestra base de datos desde algunas partes de nuestro desarrollo, lo común es configurarlo como un componente de la aplicación:

return [
    // ...
    'components' => [
        // ...
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=example',
            'username' => 'root',
            'password' => '',
            'charset' => 'utf8',
        ],
    ],
    // ...];

Para acceder a la base de datos, se utiliza Yii::$app->db.

Dependiendo de la base de datos que utilicemos, depende el nombre de origen de datos (DSN). Por ejemplo:


  • MySQL, MariaDB: mysql:host=localhost;dbname=mibasededatos
  • SQLite: sqlite:/path/al/archivo/base_de_datos
  • PostgreSQL: pgsql:host=localhost;port=5432;dbname=mibasededatos
  • CUBRID: cubrid:dbname=demodb;host=localhost;port=33000
  • MS SQL Server (vía sqlsrv driver): sqlsrv:Server=localhost;Database=mibasededatos
  • MS SQL Server (vía dblib driver): dblib:host=localhost;dbname=mibasededatos
  • MS SQL Server (vía mssql driver): mssql:host=localhost;dbname=mibasededatos
  • Oracle: oci:dbname=//localhost:1521/mibasededatos


Si nos conectamos a través de ODBC hay que configurar la propiedad yii\db\Connection::$driverName de manera similar a:

 'db' => [
  'class' => 'yii\db\Connection' ,
  'driverName' => 'mysql' ,
  'dsn' => 'odbc:Driver={MySQL};Server=localhost;Database=test' ,
  'username' => 'root' ,
  'password' => '' , 
 ],

Obviamente, también es necesario especificar el usuario y clave.

Es importante conocer que, al configurar nuestra instancia de conexión a base de datos, la conexión no se establece hasta que ejecutemos nuestra primera consulta SQL o llamemos explícitamente al método open().

Ejecutando consultas SQL

Para ejecutar consultas SQL debemos seguir los siguientes pasos:

  1. Crear la consulta SQL con yii\db\Command;
  2. Especificar los valores de nuestros parámetros (opcional);
  3. Ejecutar la consulta llamando a uno de los métodos de yii\db\Command.


A continuación unos cuantos ejemplos:

$db = new yii\db\Connection(...datos_de_conexion...);

// retorna un conjunto de filas. cada fila es una matriz asociativa de nombres y valores de las columnas.
// un arreglo vacío es devuelto si no hay resultados
$posts $db->createCommand('SELECT * FROM post')
            ->queryAll();

// retorna una única fila (la primera)
// se retorna false si no hay resultados
$post $db->createCommand('SELECT * FROM post WHERE id=1')
           ->queryOne();

// retorna a única columna (la primera)
// un arreglo vacío es devuelto si no hay resultados
$titles $db->createCommand('SELECT title FROM post')
             ->queryColumn();

// retorna un escalar
// se retorna false si no hay resultados
$count $db->createCommand('SELECT COUNT(*) FROM post')
             ->queryScalar();

Nota: Para conservar la precisión, los datos obtenidos de bases de datos están representados como cadenas, incluso si los tipos de columna de base de datos correspondientes son numéricos.

Es posible que, exactamente después de establecer la conexión a nuestra base de datos, necesitemos realizar alguna consulta, como por ejemplo para ajustar la zona horaria o el juego de carácteres. Para ello, podemos utilizar el controlador de eventos yii\db\Connection::EVENT_AFTER_OPEN de manera similar a:

return [
    // ...
    'components' => [
        // ...
        'db' => [
            'class' => 'yii\db\Connection',
            // ...
            'on afterOpen' => function($event) {
                // $event->sender se refiere a la conexión a BD
                $event->sender->createCommand("SET time_zone = 'UTC'")->execute();
            }
        ],
    ],
    // ...
];

Parámetros

Cuando creamos un comando de base de datos desde un SQL con parámetros, debemos hacerlo utilizando el método de parámetros vinculantes para prevenir ataques de inyección SQL. Por ejemplo,

$post $db->createCommand('SELECT * FROM post WHERE id=:id AND status=:status')
           ->bindValue(':id'$_GET['id'])
           ->bindValue(':status'1)
           ->queryOne();

En la sentencia SQL, se puede incrustar uno o varios marcadores de posición (por ejemplo :id en el ejemplo anterior). Un marcador de posición de parámetro debe ser una cadena que comienza con dos puntos. A continuación, se puede llamar a uno de los métodos correspondientes para enlazar los valores de los parámetros:

  • bindValue(): enlaza con un valor de parámetro único
  • bindValues(): enlaza valores de parámetro múltiples en una sola llamada
  • bindParam(): similar a bindValue() pero soporta referencias a parámetros

Los siguientes ejemplos muestran las diferentes alternativas:

$params = [':id' => $_GET['id'], ':status' => 1];
$post $db->createCommand('SELECT * FROM post WHERE id=:id AND status=:status')
           ->bindValues($params)
           ->queryOne();
           $post $db->createCommand('SELECT * FROM post WHERE id=:id AND status=:status'$params)
           ->queryOne();

El enlace de parámetros es implementado a través de sentencias preparadas, lo que a más de ayudar a evitar ataques de inyección SQL también mejora el rendimiento mediante la preparación de una sentencia SQL una sola vez y ejecutarla varias veces con diferentes parámetros. Por ejemplo,

$command $db->createCommand('SELECT * FROM post WHERE id=:id');
$post1 $command->bindValue(':id'1)->queryOne();$post2 $command->bindValue(':id'2)->queryOne();

Debido a que bindParam() admite parámetros vinculantes por referencia, el código anterior también puede escribirse como el siguiente:

$command $db->createCommand('SELECT * FROM post WHERE id=:id')
              ->bindParam(':id'$id);
$id 1;$post1 $command->queryOne();
$id 2;$post2 $command->queryOne();

Ejecución de consultas No-Select

Hasta el momento hemos visto los métodos queryAlgoMas() que permiten realizar consultas a la base de datos a través de una sentencia del tipo select. Es posible que también requiramos ejecutar sentencias como UPDATE, DELETE, INSERT para lo cual podemos utilizar el método yii\db\Command::execute() de manera similar a la siguiente:

$db->createCommand('UPDATE post SET status=1 WHERE id=1')
   ->execute();

El método  yii\db\Command::execute() retorna el número de filas afectadas por la sentencia.

También podemos llamar a  insert(), update(), delete() para construir el correspondiente SQL indicando el nombre de la tabla, columnas y valores.

// INSERT (tabla, columnas y valores)
$db->createCommand()->insert('usuario', [
    'nombre' => 'Santiago',
    'edad' => 30,
])->execute();

// UPDATE (tabla, columnas y valores, condición)
$db->createCommand()->update('usuario', ['estado' => 1], 'edad > 30')->execute();
// DELETE (tabla, condición)
$db->createCommand()->delete('usuario''estado = 0')->execute();

Y si lo que requerimos es insertar múltiples filas se puede utilizar batchInsert(), lo cual es más eficiente al momento de insertar varias filas que de una en una.

// tabla, columnas, valores
$db->createCommand()->batchInsert('usuario', ['nombre''edad'], [
    ['Tomás'30],
    ['Lorena'20],
    ['Linda'25],
])->execute();



También te puede interesar:
Trabajando con bases de datos
Generador de Consultas (Query Builder)
Active Record (Registro Activo)

miércoles, 21 de enero de 2015

Configuraciones

Las configuraciones se utilizan ampliamente en Yii al crear nuevos objetos o inicializar los objetos existentes. Las configuraciones por lo general incluyen el nombre de la clase objeto que se está creando, y una lista de valores iniciales que se deben asignar a las propiedades del objeto. Las configuraciones también pueden incluir una lista de los controladores que deben concederse a las eventos y/o una lista de comportamientos que también serán añadidas al objeto.

A continuación, una configuración para crear e inicializar una conexión de base de datos:

$config = [
    'class' => 'yii\db\Connection',
    'dsn' => 'mysql:host=127.0.0.1;dbname=demo',
    'username' => 'root',
    'password' => '',
    'charset' => 'utf8',
];
$db Yii::createObject($config);

El método Yii::createObject() toma un arreglo configuración como su argumento y crea un objeto creando una instancia de la clase llamada en la configuración. Cuando se crea una instancia del objeto, el resto de la configuración se utiliza para inicializar las propiedades del objeto, controladores de eventos y comportamientos.

Si ya se tiene un objeto, se puede utilizar Yii::configure() para inicializar las propiedades del objeto con un arreglo de configuración:

Yii::configure($object$config);

Nótese que en este caso, el arreglo de configuración no debe tener un elemento class.

Formato de Configuración

El formato de una configuración se puede describir formalmente como:

[
    'class' => 'ClassName',
    'propertyName' => 'propertyValue',
    'on eventName' => $eventHandler,
    'as behaviorName' => $behaviorConfig,
]

donde:

  • class especifica un nombre de clase completo para el objeto que se está creando.
  • propertyName especifica los valores iniciales de la propiedad con nombre. Las índices son los nombres de las propiedades y los valores son los valores iniciales correspondientes. Sólo las variables miembro públicas y propiedades definidas por getters/setters pueden configurarse.
  • on eventName indica los controladores que deberán adjuntarse a los eventos del objeto. Nótese que los índices del arreglo se forman con el prefijo on.
  • as behaviorName indica qué comportamientos deben estar adjuntos al objeto. Nótese que los índices del arreglo se forman con el prefijo as; el valor, $behaviorConfig, representa la configuración para la creación de un comportamiento, como una configuración normal descrita aquí.


A continuación se muestra un ejemplo que muestra una configuración con los valores iniciales de las propiedades, controladores de eventos y comportamientos:

[
    'class' => 'app\components\SearchEngine',
    'apiKey' => 'xxxxxxxx',
    'on search' => function ($event) {
        Yii::info("Término buscado: " $event->keyword);
    },
    'as indexer' => [
        'class' => 'app\components\IndexerBehavior',
        // ... valores iniciales de las propiedades ...
    ],
]

Utilizando Configuraciones

Las configuraciones se utilizan en muchos lugares en Yii. Vamos a describir configuraciones de aplicaciones y configuraciones para widget, dos principales usos de configuraciones.

Configuraciones de aplicación

La configuración de una aplicación es probablemente uno de los más complejos arreglos en Yii. Esto se debe a la clase application tiene un montón de propiedades y eventos configurables. Más importante aún, las propiedades de sus componentes puede recibir una gran variedad de configuraciones para crear componentes que se registran a través de la aplicación. El siguiente es un resumen del archivo de configuración de la aplicación para la plantilla de aplicación básica.

$config = [
    'id' => 'basic',
    'basePath' => dirname(__DIR__),
    'extensions' => require(__DIR__ '/../vendor/yiisoft/extensions.php'),
    'components' => [
        'cache' => [
            'class' => 'yii\caching\FileCache',
        ],
        'mailer' => [
            'class' => 'yii\swiftmailer\Mailer',
        ],
        'log' => [
            'class' => 'yii\log\Dispatcher',
            'traceLevel' => YII_DEBUG 0,
            'targets' => [
                [
                    'class' => 'yii\log\FileTarget',
                ],
            ],
        ],
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=stay2',
            'username' => 'root',
            'password' => '',
            'charset' => 'utf8',
        ],
    ],
];

Como se puede notar, la configuración no tiene un índice class. Esto se debe a que se utiliza en el script de entrada, donde ya se le da el nombre de la clase,

(new yii\web\Application($config))->run();

Configuraciones para Widgets

Al utilizar los widgets , a menudo es necesario utilizar las configuraciones para personalizar las propiedades de los mismos. Tanto los métodos yii\base\Widget::widget() y yii\base\Widget::begin() pueden ser utilizados para crear un widget. En ambos casos toman un arreglo de configuración como el siguiente:

use yii\widgets\Menu;

echo Menu::widget([
    'activateItems' => false,
    'items' => [
        ['label' => 'Home''url' => ['site/index']],
        ['label' => 'Products''url' => ['product/index']],
        ['label' => 'Login''url' => ['site/login'], 'visible' => Yii::$app->user->isGuest],
    ],
]);

El código anterior crea un widget Menu e inicializa su propiedad activateItems a false. La propiedad items también se configura con los elementos del menú que se mostrarán.

Archivos de Configuración

Cuando una configuración es muy compleja, una práctica común es almacenarlo en uno o varios archivos PHP, conocidos como archivos de configuración. Un archivo de configuración devuelve un arreglo PHP que representa la configuración. Por ejemplo, es posible mantener una configuración de la aplicación en un archivo llamado web.php como la siguiente:

return [
    'id' => 'basic',
    'basePath' => dirname(__DIR__),
    'extensions' => require(__DIR__ '/../vendor/yiisoft/extensions.php'),
    'components' => require(__DIR__ '/components.php'),
];

Puesto que la configuración de los componentes también es compleja, se la puede almacenar en el archivo components.php e incluirla (require) desde éste archivo web.php tal como lo muestra el ejemplo. A su vez, el archivo components.php tendría:

return [
    'cache' => [
        'class' => 'yii\caching\FileCache',
    ],
    'mailer' => [
        'class' => 'yii\swiftmailer\Mailer',
    ],
    'log' => [
        'class' => 'yii\log\Dispatcher',
        'traceLevel' => YII_DEBUG 0,
        'targets' => [
            [
                'class' => 'yii\log\FileTarget',
            ],
        ],
    ],
    'db' => [
        'class' => 'yii\db\Connection',
        'dsn' => 'mysql:host=localhost;dbname=stay2',
        'username' => 'root',
        'password' => '',
        'charset' => 'utf8',
    ],
];

Para obtener una configuración guardada en un archivo de configuración solamente se la debe incluir utilizando require:

$config = require('path/to/web.php');
(new yii\web\Application($config))->run();

Configuraciones predeterminadas

El método Yii::createObject() se implementa en base a un contenedor de inyección de dependencias. Esto permite especificar un conjunto de las llamadas configuraciones predeterminadas que se aplicarán a todas las instancias de las clases especificadas cuando se creen usando Yii::createObject(). Las configuraciones predeterminadas se pueden especificar llamando a Yii::$container->set() en el código bootstrapping.

Por ejemplo, si se desea personalizar yii\widgets\LinkPager para que al paginar se muestren hasta 5 botones de página (el valor predeterminado es 10) se puede utilizar el siguiente código para tal objetivo:

\Yii::$container->set('yii\widgets\LinkPager', [
    'maxButtonCount' => 5,
]);

En este caso, si no se utilizara la configuración por defecto, habría que configurar maxButtonCount en cada lugar que se pagine.

Variables de Ambiente

Las configuraciones a menudo varían de acuerdo con el entorno en el que una aplicación se ejecuta. Por ejemplo, en el ambiente de desarrollo, es posible que se desee utilizar una base de datos llamada mydb_dev, mientras que en el servidor de producción es posible que se desee utilizar la base de datos mydb_prod base de datos. Para facilitar entornos de conmutación, Yii proporciona una constante llamada YII_ENV que se puede definir en el script de entrada. Por ejemplo,

defined('YII_ENV') or define('YII_ENV''dev');

Se puede definir YII_ENV con uno de los siguientes valores:

  • prod: ambiente de producción. La constante YII_ENV_PROD se evaluará como verdadero. Este es el valor por defecto de YII_ENV si no se lo define.
  • dev: ambiente de desarrollo. La constante YII_ENV_DEV se evaluará como verdadero.
  • test: ambiente de pruebas. La constante YII_ENV_TEST se evaluará como verdadero.

Con estas constantes de ambiente se puede especificar las condiciones iniciales basados en el ambiente actual. Por ejemplo, nuestra configuración de aplicación puede contener el siguiente código para habilitar la barra de depuración y depurador en nuestro ambiente de desarrollo:

$config = [...];

if (YII_ENV_DEV) {
    // configuración para ambiente de desarrollo 'dev'
    $config['bootstrap'][] = 'debug';
    $config['modules']['debug'] = 'yii\debug\Module';
}

return $config;


También te puede interesar:
Comportamientos (Behaviors)
Eventos
Propiedades
Componentes