网站首页 » Yii » Yii 推荐的数据库操作的方式

Yii 推荐的数据库操作的方式

July 1, 2020 Yii

Yii 进行数据库操作有两种方式

推荐方式 创建模型类,继承 Active Record 类

在models文件夹中创建模型类文件,在controller 中首先实例化模型,然后通过模型进行数据库操作。

  • 可对表前缀进行控制
  • 写法简单, 与Tp, Laravel 写法通用
  • 支持对查询出的值进行类型转换
  • 支持Json序列化及反序列化
  • 定义表关联关系

数据库连接配置文件 config/db.php

<?php

return [
    'class' => 'yii\db\Connection',
    'dsn' => 'mysql:host=localhost;dbname=yiibasic',
    'username' => 'root',
    'password' => '12345678',
    'charset' => 'utf8',
    'tablePrefix' => 'tbl_'        //定义了表前缀


    // Schema cache options (for production environment)
    //'enableSchemaCache' => true,
    //'schemaCacheDuration' => 60,
    //'schemaCache' => 'cache',
];

模型类文件 models/Customer.php

<?php

/**
 * tbl_customer 表模型类
 */

namespace app\models;


use yii\db\ActiveRecord;

class Customer extends ActiveRecord
{
 const STATUS_INACTIVE = 0;
 const STATUS_ACTIVE = 1;

 /**
  * 返回 active record 类关联的数据表名称, %为表前缀的占位符
  * @return string
  */
 public static function tableName()
 {
     return '{{%customer}}'; // TODO: Change the autogenerated stub
 }

}

使用查询构造器 yiidbQuery

$query = new Query();
        $list = $query
            ->where('name like :name', [':name' => "%张三%"])
            ->orWhere('age > 1')
            ->from("user")
            ->orderBy("id DESC")
            ->all();
        var_dump($list);

继承Active Record类的模型类查询两个重要的特点

  • 延迟加载和即时加载

在 访问关联数据 中,我们解释说可以像问正常的对象属性那样 访问 Active Record 实例的关联属性。SQL 语句仅在 你第一次访问关联属性时执行。我们称这种关联数据访问方法为 延迟加载。 例如,

// SELECT * FROM `customer` WHERE `id` = 123
$customer = Customer::findOne(123);

// SELECT * FROM `order` WHERE `customer_id` = 123
$orders = $customer->orders;

// 没有 SQL 语句被执行
$orders2 = $customer->orders;

延迟加载使用非常方便。但是,当你需要访问相同的具有多个 Active Record 实例的关联属性时, 可能会遇到性能问题。请思考一下以下代码示例。 有多少 SQL 语句会被执行?

// SELECT * FROM `customer` LIMIT 100
$customers = Customer::find()->limit(100)->all();

foreach ($customers as $customer) {
    // SELECT * FROM `order` WHERE `customer_id` = ...
    $orders = $customer->orders;
}

你瞅瞅,上面的代码会产生 101 次 SQL 查询! 这是因为每次你访问 for 循环中不同的 Customer 对象的 orders 关联属性时,SQL 语句 都会被执行一次。

为了解决上述的性能问题,你可以使用所谓的 即时加载,如下所示,

// SELECT * FROM `customer` LIMIT 100;
// SELECT * FROM `orders` WHERE `customer_id` IN (...)
$customers = Customer::find()
    ->with('orders')
    ->limit(100)
    ->all();

foreach ($customers as $customer) {
    // 没有任何的 SQL 执行
    $orders = $customer->orders;
}

通过调用 yiidbActiveQuery::with() 方法,你使 Active Record 在一条 SQL 语句里就返回了这 100 位客户的订单。 结果就是,你把要执行的 SQL 语句从 101 减少到 2 条!

提示: 如果你在即时加载的关联中调用 select() 方法,你要确保 在关联声明中引用的列必须被 select。否则,相应的模型(Models)可能 无法加载。例如,

$orders = Order::find()->select(['id', 'amount'])->with('customer')->all();
// $orders[0]->customer 会一直是 `null`。你应该这样写,以解决这个问题:
$orders = Order::find()->select(['id', 'amount', 'customer_id'])->with('customer')->all();
添加新评论