start-databases.md 11.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Trabalhando com Bancos de Dados
===============================

Esta seção descreverá como criar uma nova página que exibe dados de países
buscados de uma tabela do banco de dados chamada `country`. Para isso, você
configurará uma conexão com o banco de dados, criará uma classe de
[Active Record](db-active-record.md), definirá uma [action](structure-controllers.md) (ação),
e criará uma [view](structure-views.md) (visão).

Através deste tutorial, você aprenderá como:

* Configurar uma conexão de BD
* Definir uma classe de Active Record
* Consultar dados usando a classe de Active Record
15
* Exibir dados em uma view de forma paginada
16 17 18

Perceba que para terminar essa seção, você deve ter conhecimento e experiência
básica usando bancos de dados. Em particular, você deveria saber como criar um
19
banco de dados, e como executar instruções SQL usando uma ferramenta de cliente
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
de BD.


Preparando o Banco de Dados <a name="preparing-database"></a>
---------------------------

Para começar, crie um banco de dados chamado `yii2basic`, a partir do qual você
buscará os dados em sua aplicação. Você pode criar um banco de dados SQLite, MySQL,
PostgreSQL, MSSQL ou Oracle, já que o Yii tem suporte embutido a muitas aplicações
de bancos de dados. Por questões de simplicidade, será assumido o uso do MySQL
na descrição a seguir.

Em seguida, crie uma tabela chamada `country` no banco de dados, e insira alguns
dados de exemplo. Você pode rodar as seguintes declarações SQL para fazê-lo:

```sql
CREATE TABLE `country` (
  `code` CHAR(2) NOT NULL PRIMARY KEY,
  `name` CHAR(52) NOT NULL,
  `population` INT(11) NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `country` VALUES ('AU','Australia',18886000);
INSERT INTO `country` VALUES ('BR','Brazil',170115000);
INSERT INTO `country` VALUES ('CA','Canada',1147000);
INSERT INTO `country` VALUES ('CN','China',1277558000);
INSERT INTO `country` VALUES ('DE','Germany',82164700);
INSERT INTO `country` VALUES ('FR','France',59225700);
INSERT INTO `country` VALUES ('GB','United Kingdom',59623400);
INSERT INTO `country` VALUES ('IN','India',1013662000);
INSERT INTO `country` VALUES ('RU','Russia',146934000);
INSERT INTO `country` VALUES ('US','United States',278357000);
```

Neste ponto, você tem um banco de dados chamado `yii2basic`, e dentro dele uma
tabela `country` com três colunas, contendo dez linhas de dados.

Configurando uma Conexão do BD <a name="configuring-db-connection"></a>
------------------------------

Antes de prosseguir, certifique-se de que você possui instalados tanto a
extensão [PDO](http://www.php.net/manual/en/book.pdo.php) do PHP quanto o driver
do PDO para a base que você está usando (por exemplo, `pdo_mysql` para o MySQL).
Este é um requisito básico se a sua aplicação usa um banco de dados relacional.

Tendo estes instalados, abra o arquivo `config/db.php` e mude os parâmetros para
que estejam corretos para o seu banco de dados. Por padrão, o arquivo contém
o seguinte:

```php
<?php

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

O arquivo `config/db.php` é uma ferramenta de [configuração](concept-configurations.md)
típica baseada em arquivos. Este arquivo de configuração em particular especifica
os parâmetros necessários para criar e inicializar uma instância de [[yii\db\Connection]]
através da qual você pode fazer consultas de SQL ao banco de dados subjacente.

A conexão de BD configurada acima pode ser acessada no código da aplicação
através da expressão `Yii::$app->db`.

89
> Informação: O arquivo `config/db.php` será incluso pela configuração principal da
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
  aplicação `config/web.php`, que especifica como a instância da [aplicação](structure-applications.md)
  deverá ser inicializada. Para mais informações, por favor consulte a seção sobre [Configurações](concept-configurations.md).


Criando um Active Record <a name="creating-active-record"></a>
------------------------

Para representar e buscar os dados da tabela `country`, crie uma classe que
deriva de [Active Record](db-active-record.md) chamada `Country`, e salve-a
no arquivo `models/Country.php`.

```php
<?php

namespace app\models;

use yii\db\ActiveRecord;

class Country extends ActiveRecord
{
}
```

A classe `Country` estende de [[yii\db\ActiveRecord]]. Você não precisa escrever
nenhum código nela! Só com o código acima, o Yii adivinhará o nome da tabela
associada a partir do nome da classe.

117
> Informação: Se não houver nenhuma correspondência direta do nome da classe com o nome
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
  da tabela, você pode sobrescrever o método [[yii\db\ActiveRecord::tableName()]] 
  para especificar explicitamente o nome da tabela associada.

Usando a classe `Country`, você pode manipular facilmente os dados na tabela
`country`, conforme é demonstrado nestes fragmentos:

```php
use app\models\Country;

// obtém todas as linhas da tabela country e as ordena pela coluna "name"
$countries = Country::find()->orderBy('name')->all();

// obtém a linha cuja chave primária é "US"
$country = Country::findOne('US');

// exibe "United States"
echo $country->name;

// altera o nome do país para ser "U.S.A." e o salva no banco de dados
$country->name = 'U.S.A.';
$country->save();
```

141 142
> Informação: O Active Record é uma maneira poderosa de acessar e manipular os dados
  do banco de dados de uma forma orientada a objeto. Você pode encontrar informações
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
  mais detalhadas na seção [Active Record](db-active-record.md). Alternativamente,
  você também pode interagir com o banco de dados usando um método de acesso aos
  dados de baixo nível chamado [Data Access Objects](db-dao.md).


Criando uma Action <a name="creating-action"></a>
------------------

Para expor os dados de países aos usuários finais, você precisaria de uma nova
action. Ao invés de colocar a nova action no controller (controlador) `site`,
como você fez nas seções anteriores, faz mais sentido criar um novo controller
especificamente para todas as actions relacionadas aos dados de países. Chame
este novo controller de `CountryController`, e crie uma action `index` nele,
conforme o exemplo a seguir.

```php
<?php

namespace app\controllers;

use yii\web\Controller;
use yii\data\Pagination;
use app\models\Country;

class CountryController extends Controller
{
    public function actionIndex()
    {
        $query = Country::find();

        $pagination = new Pagination([
            'defaultPageSize' => 5,
            'totalCount' => $query->count(),
        ]);

        $countries = $query->orderBy('name')
            ->offset($pagination->offset)
            ->limit($pagination->limit)
            ->all();

        return $this->render('index', [
            'countries' => $countries,
            'pagination' => $pagination,
        ]);
    }
}
```

Salve o código acima em um arquivo `controllers/CountryController.php`.

A action `index` chama `Country::find()`. Este método do Active Record constrói
uma consulta do BD e retorna todos os dados da tabela `country`. Para limitar o
número de países retornados em cada requisição, a consulta é paginada com a ajuda
de um objeto [[yii\data\Pagination]]. O objeto `Pagination` serve para dois propósitos:

* Definir as cláusulas `offset` e `limit` da declaração SQL representada pela
  consulta de modo que apenas retorne uma única página de dados por vez (no máximo
  5 linhas por página).
* É usado para que a view exiba um paginador que consite de uma lista de botões
  para as páginas, conforme será explicado na próxima sub-seção.

No final do código, a action `index` renderiza uma view chamada `index`, e passa
para ela os dados dos países bem como as informações de paginação.


Criando uma View <a name="creating-view"></a>
----------------

Dentro do diretório `views`, primeiro crie um sub-diretório chamado `country`.
Esta pasta será usada para guardar todas as views renderizadas pelo controller
`country`. Dentro do diretório `views/country`, crie um arquivo `index.php`
contendo o seguinte:

```php
<?php
use yii\helpers\Html;
use yii\widgets\LinkPager;
?>
<h1>Countries</h1>
<ul>
<?php foreach ($countries as $country): ?>
    <li>
        <?= Html::encode("{$country->name} ({$country->code})") ?>:
        <?= $country->population ?>
    </li>
<?php endforeach; ?>
</ul>

<?= LinkPager::widget(['pagination' => $pagination]) ?>
```

A view tem duas seções relativas à exibição dos dados dos países. Na primeira parte,
os dados de países fornecidos são cruzados e renderizados como uma lista do HTML.
Na segunda parte, um widget [[yii\widgets\LinkPager]] é renderizado usando as
informações de paginação passadas pela action. O widget `LinkPager` exibe uma
lista de botões para as páginas. Ao clicar em qualquer um deles atualizará
os dados dos países com a página correspondente.


Testando <a name="trying-it-out"></a>
--------

245
Para verificar se todo os códigos acima funcionam, use o seu navegador para
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
acessar a seguinte URL:

```
http://hostname/index.php?r=country/index
```

![Lista de Países](images/start-country-list.png)

Primeiramente, você verá uma lista exibindo cinco países. Abaixo dos países,
você verá um paginador com quatro botões. Se você clicar no botão "2", você
verá a página exibindo outros cinco países no banco de dados: a segunda
página de registros. Observe mais cuidadosamente e você perceberá que a URL no
browser mudou para

```
http://hostname/index.php?r=country/index&page=2
```

Por baixo dos panos, [[yii\data\Pagination|Pagination]] está fornecendo toda
a funcionalidade necessária para paginar um conjunto de dados:

* Inicialmente, [[yii\data\Pagination|Pagination]] representa a primeira página,
  que reflete a consulta SELECT de países com a cláusula `LIMIT 5 OFFSET 0`.
  Como resultado, os primeiros cinco países serão buscados e exibidos.
* O widget [[yii\widgets\LinkPager|LinkPager]] renderiza os botões das páginas
  usando as URLs criadas pelo [[yii\data\Pagination::createUrl()|Pagination]].
  As URLs conterão um parâmetro `page`, que representa os diferentes números de
  páginas.
* Se você clicar no botão da página "2", uma nova requisição para a rota
  `country/index` será disparada e tratada. [[yii\data\Pagination|Pagination]] lê
  o parâmetro `page` da URL e define o número da página atual como sendo 2. A nova
  consulta de países então terá a cláusula `LIMIT 5 OFFSET 5` e retornará os
  próximos cinco países para a exibição.


Resumo <a name="summary"></a>
------

Nesta seção, você aprendeu como trabalhar com um banco de dados. Você também
aprendeu como buscar e exibir dados em páginas com a ajuda do
[[yii\data\Pagination]] e do [[yii\widgets\LinkPager]].

Na próxima seção, você aprenderá como usar a poderosa ferramenta geradora de códigos,
chamada [Gii](tool-gii.md), para ajudá-lo a implementar rapidamente algumas
funcionalidades comumente necessárias, tais como as operações CRUD
(Criar-Ler-Atualizar-Excluir) para trabalhar com os dados em uma tabela do
banco de dados. Na verdade, todo o código que você acabou de escrever pode ser
gerado automaticamente no Yii usando a ferramenta Gii.