metheoryt
10 years ago
1 changed files with 252 additions and 0 deletions
@ -0,0 +1,252 @@ |
|||||||
|
Работа с базами данных |
||||||
|
====================== |
||||||
|
|
||||||
|
Этот раздел расскажет о том, как создать новую страницу, отображающую данные по странам, полученные из таблицы `countries` базы данных. Для достижения этой цели вам будет необходимо настроить подключение к базе данных, создать класс [Active Record](db-active-record.md), определить [action](structure-controllers.md), и создать [view](structure-views.md). |
||||||
|
|
||||||
|
Изучив эту часть, вы научитесь: |
||||||
|
|
||||||
|
* Настраивать подключение к БД |
||||||
|
* Определять класс Active Record |
||||||
|
* Запрашивать данные, используя класс Active Record |
||||||
|
* Отображать данные в виде с использованием пагинации |
||||||
|
|
||||||
|
Обратите внимание, чтобы усвоить этот раздел, вы должны иметь базовые знания и навыки использования баз данных. |
||||||
|
В частности, вы должны знать, как создать базу данных, и как выполнять SQL запросы, используя клиентские инструменты для работы с БД. |
||||||
|
|
||||||
|
Подготавливаем базу данных <a name="preparing-database"></a> |
||||||
|
---------------------- |
||||||
|
|
||||||
|
Для начала, создайте базу данных под названием `yii2basic`, из которой вы будете получать данные в вашем приложении. |
||||||
|
Вы можете создать базу данных SQLite, MySQL, PostgreSQL, MSSQL или Oracle, так как Yii имеет встроенную поддержку для многих баз данных. Для простоты, в дальнейшем описании будет подразумеваться MySQL. |
||||||
|
|
||||||
|
После этого создайте в базе данных таблицу `country`, и добавьте в неё немного демонстрационных данных. Вы можете запустить следующую SQL инструкцию, чтобы сделать это: |
||||||
|
```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); |
||||||
|
``` |
||||||
|
|
||||||
|
На данный момент у вас есть база данных под названием `yii2basic`, и внутри неё таблица `country` с тремя столбцами, содержащими десять строк данных. |
||||||
|
|
||||||
|
Настраиваем подключение к БД <a name="configuring-db-connection"></a> |
||||||
|
--------------------------- |
||||||
|
|
||||||
|
Before proceeding, make sure you have installed both the [PDO](http://www.php.net/manual/en/book.pdo.php) PHP extension and |
||||||
|
the PDO driver for the database you are using (e.g. `pdo_mysql` for MySQL). This is a basic requirement |
||||||
|
if your application uses a relational database. |
||||||
|
|
||||||
|
With those installed, open the file `config/db.php` and change the parameters to be correct for your database. By default, |
||||||
|
the file contains the following: |
||||||
|
|
||||||
|
```php |
||||||
|
<?php |
||||||
|
|
||||||
|
return [ |
||||||
|
'class' => 'yii\db\Connection', |
||||||
|
'dsn' => 'mysql:host=localhost;dbname=yii2basic', |
||||||
|
'username' => 'root', |
||||||
|
'password' => '', |
||||||
|
'charset' => 'utf8', |
||||||
|
]; |
||||||
|
``` |
||||||
|
|
||||||
|
The `config/db.php` file is a typical file-based [configuration](concept-configurations.md) tool. This particular configuration file specifies the parameters |
||||||
|
needed to create and initialize a [[yii\db\Connection]] instance through which you can make SQL queries |
||||||
|
against the underlying database. |
||||||
|
|
||||||
|
The DB connection configured above can be accessed in the application code via the expression `Yii::$app->db`. |
||||||
|
|
||||||
|
> Info: The `config/db.php` file will be included by the main application configuration `config/web.php`, |
||||||
|
which specifies how the [application](structure-applications.md) instance should be initialized. |
||||||
|
For more information, please refer to the [Configurations](concept-configurations.md) section. |
||||||
|
|
||||||
|
|
||||||
|
Creating an Active Record <a name="creating-active-record"></a> |
||||||
|
------------------------- |
||||||
|
|
||||||
|
To represent and fetch the data in the `country` table, create an [Active Record](db-active-record.md)-derived |
||||||
|
class named `Country`, and save it in the file `models/Country.php`. |
||||||
|
|
||||||
|
```php |
||||||
|
<?php |
||||||
|
|
||||||
|
namespace app\models; |
||||||
|
|
||||||
|
use yii\db\ActiveRecord; |
||||||
|
|
||||||
|
class Country extends ActiveRecord |
||||||
|
{ |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
The `Country` class extends from [[yii\db\ActiveRecord]]. You do not need to write any code inside of it! With just the above code, |
||||||
|
Yii will guess the associated table name from the class name. |
||||||
|
|
||||||
|
> Info: If no direct match can be made from the class name to the table name, you can |
||||||
|
override the [[yii\db\ActiveRecord::tableName()]] method to explicitly specify the associated table name. |
||||||
|
|
||||||
|
Using the `Country` class, you can easily manipulate data in the `country` table, as shown in these snippets: |
||||||
|
|
||||||
|
```php |
||||||
|
use app\models\Country; |
||||||
|
|
||||||
|
// get all rows from the country table and order them by "name" |
||||||
|
$countries = Country::find()->orderBy('name')->all(); |
||||||
|
|
||||||
|
// get the row whose primary key is "US" |
||||||
|
$country = Country::findOne('US'); |
||||||
|
|
||||||
|
// displays "United States" |
||||||
|
echo $country->name; |
||||||
|
|
||||||
|
// modifies the country name to be "U.S.A." and save it to database |
||||||
|
$country->name = 'U.S.A.'; |
||||||
|
$country->save(); |
||||||
|
``` |
||||||
|
|
||||||
|
> Info: Active Record is a powerful way to access and manipulate database data in an object-oriented fashion. |
||||||
|
You may find more detailed information in the [Active Record](db-active-record.md) section. Alternatively, you may also interact with a database using a lower-level data accessing method called [Data Access Objects](db-dao.md). |
||||||
|
|
||||||
|
|
||||||
|
Creating an Action <a name="creating-action"></a> |
||||||
|
------------------ |
||||||
|
|
||||||
|
To expose the country data to end users, you need to create a new action. Instead of placing the new action in the `site` |
||||||
|
controller, like you did in the previous sections, it makes more sense to create a new controller specifically |
||||||
|
for all actions related to the country data. Name this new controller `CountryController`, and create |
||||||
|
an `index` action in it, as shown in the following. |
||||||
|
|
||||||
|
```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, |
||||||
|
]); |
||||||
|
} |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
Save the above code in the file `controllers/CountryController.php`. |
||||||
|
|
||||||
|
The `index` action calls `Country::find()`. This Active Record method builds a DB query and retrieves all of the data from the `country` table. |
||||||
|
To limit the number of countries returned in each request, the query is paginated with the help of a |
||||||
|
[[yii\data\Pagination]] object. The `Pagination` object serves two purposes: |
||||||
|
|
||||||
|
* Sets the `offset` and `limit` clauses for the SQL statement represented by the query so that it only |
||||||
|
returns a single page of data at a time (at most 5 rows in a page). |
||||||
|
* It's used in the view to display a pager consisting of a list of page buttons, as will be explained in |
||||||
|
the next subsection. |
||||||
|
|
||||||
|
At the end of the code, the `index` action renders a view named `index`, and passes the country data as well as the pagination |
||||||
|
information to it. |
||||||
|
|
||||||
|
|
||||||
|
Creating a View <a name="creating-view"></a> |
||||||
|
--------------- |
||||||
|
|
||||||
|
Under the `views` directory, first create a sub-directory named `country`. This folder will be used to hold all the |
||||||
|
views rendered by the `country` controller. Within the `views/country` directory, create a file named `index.php` |
||||||
|
containing the following: |
||||||
|
|
||||||
|
```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]) ?> |
||||||
|
``` |
||||||
|
|
||||||
|
The view has two sections relative to displaying the country data. In the first part, the provided country data is traversed and rendered as an unordered HTML list. |
||||||
|
In the second part, a [[yii\widgets\LinkPager]] widget is rendered using the pagination information passed from the action. |
||||||
|
The `LinkPager` widget displays a list of page buttons. Clicking on any of them will refresh the country data |
||||||
|
in the corresponding page. |
||||||
|
|
||||||
|
|
||||||
|
Trying it Out <a name="trying-it-out"></a> |
||||||
|
------------- |
||||||
|
|
||||||
|
To see how all of the above code works, use your browser to access the following URL: |
||||||
|
|
||||||
|
``` |
||||||
|
http://hostname/index.php?r=country/index |
||||||
|
``` |
||||||
|
|
||||||
|
![Country List](images/start-country-list.png) |
||||||
|
|
||||||
|
At first, you will see a page showing five countries. Below the countries, you will see a pager with four buttons. |
||||||
|
If you click on the button "2", you will see the page display another five countries in the database: the second page of records. |
||||||
|
Observe more carefully and you will find that the URL in the browser also changes to |
||||||
|
|
||||||
|
``` |
||||||
|
http://hostname/index.php?r=country/index&page=2 |
||||||
|
``` |
||||||
|
|
||||||
|
Behind the scenes, [[yii\data\Pagination|Pagination]] is providing all of the necessary functionality to paginate a data set: |
||||||
|
|
||||||
|
* Initially, [[yii\data\Pagination|Pagination]] represents the first page, which reflects the country SELECT query |
||||||
|
with the clause `LIMIT 5 OFFSET 0`. As a result, the first five countries will be fetched and displayed. |
||||||
|
* The [[yii\widgets\LinkPager|LinkPager]] widget renders the page buttons using the URLs |
||||||
|
created by [[yii\data\Pagination::createUrl()|Pagination]]. The URLs will contain the query parameter `page`, which |
||||||
|
represents the different page numbers. |
||||||
|
* If you click the page button "2", a new request for the route `country/index` will be triggered and handled. |
||||||
|
[[yii\data\Pagination|Pagination]] reads the `page` query parameter from the URL and sets the current page number to 2. |
||||||
|
The new country query will thus have the clause `LIMIT 5 OFFSET 5` and return the next five countries |
||||||
|
for display. |
||||||
|
|
||||||
|
|
||||||
|
Summary <a name="summary"></a> |
||||||
|
------- |
||||||
|
|
||||||
|
In this section, you learned how to work with a database. You also learned how to fetch and display |
||||||
|
data in pages with the help of [[yii\data\Pagination]] and [[yii\widgets\LinkPager]]. |
||||||
|
|
||||||
|
In the next section, you will learn how to use the powerful code generation tool, called [Gii](tool-gii.md), |
||||||
|
to help you rapidly implement some commonly required features, such as the Create-Read-Update-Delete (CRUD) |
||||||
|
operations for working with the data in a database table. As a matter of fact, the code you have just written can all |
||||||
|
be automatically generated in Yii using the Gii tool. |
Loading…
Reference in new issue