概述
本文整合 Laravel 与 Yii 2 框架数据库操作的核心方法、语法差异、逐行对照及错误排查,既覆盖单框架实操,也满足跨框架开发切换需求,适合 PHP 开发者快速上手和灵活适配。
一、Laravel 数据库操作基础
Laravel 提供 Eloquent ORM、查询构造器(DB 门面)、原生 SQL 三种操作方式,兼顾优雅性与灵活性,自动防范 SQL 注入。
1. 数据库配置
配置文件位于 config/database.php,实际开发中通过根目录 .env 文件配置连接信息,框架自动读取覆盖默认值:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_demo
DB_USERNAME=root
DB_PASSWORD=your_password
2. 核心操作方式
(1)查询构造器(DB 门面,无模型)
无需创建数据表模型,通过 DB 门面直接操作,语法简洁流畅:
use Illuminate\Support\Facades\DB;
// 基础查询
public function index()
{
$data = DB::table('core_region')
->select(['national_code', 'region_name', 'parent_id'])
->where('national_code', '<', 110117)
->offset(15) // 跳过前15条
->limit(10) // 获取10条
->orderBy('national_code', 'desc')
->get();
return $data->toArray(); // 结果转数组
}
(2)Eloquent ORM(模型驱动)
模型与数据表映射,面向对象风格,适合复杂业务逻辑,需在 app/Models 目录创建模型:
// app/Models/User.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected $table = 'users'; // 手动指定表名(默认模型名复数)
protected $fillable = ['name', 'email', 'password']; // 允许批量赋值字段
public $timestamps = true; // 自动维护 created_at/updated_at
}
ORM 基础操作:
use App\Models\User;
// 查询
$user = User::find(1); // 按主键查询,无结果返回null
$users = User::where('status', 1)->orderBy('id', 'desc')->get()->toArray();
// 新增
User::create(['name' => 'test', 'email' => 'test@example.com']);
// 更新
$user->name = 'new name';
$user->save();
// 删除
User::destroy([1,2,3]); // 按主键批量删除
(3)事务处理
// 自动事务(推荐,支持重试次数)
DB::transaction(function () {
User::create(['name' => 'test']);
Order::create(['user_id' => 1]);
}, 5); // 死锁时重试5次
// 手动事务
DB::beginTransaction();
try {
// 业务逻辑
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
throw $e;
}
二、Yii 2 数据库操作基础
Yii 2 以 Active Record(AR)模型为核心,需生成数据表模型,支持查询构建器和原生 SQL,配置化程度高。
1. 数据库配置
配置文件位于 config/db.php:
return [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=127.0.0.1;dbname=yii_demo',
'username' => 'root',
'password' => 'your_password',
'charset' => 'utf8',
];
2. 核心操作方式
(1)Active Record(AR 模型,推荐)
通过 Gii 代码生成器(访问 website/gii)创建模型,继承 yii\db\ActiveRecord,必须关联具体模型文件:
// app/models/ProductCategory.php
namespace app\models;
use yii\db\ActiveRecord;
class ProductCategory extends ActiveRecord
{
// 必须手动指定表名
public static function tableName()
{
return 'product_category';
}
}
AR 基础操作:
use app\models\ProductCategory;
// 查询(结果直接转数组)
$list = ProductCategory::find()
->select(['category_id', 'category_name'])
->where(['level' => 1, 'is_delete' => 0])
->asArray() // 前置指定返回数组
->all();
// 新增
$category = new ProductCategory();
$category->category_name = '测试分类';
$category->save();
// 更新
ProductCategory::updateAll(['is_delete' => 1], ['category_id' => 1]);
// 删除
$category = ProductCategory::findOne(1);
$category->delete();
(2)查询构建器(无模型)
无模型时需实例化 yii\db\Query 类,语法偏向配置式:
use yii\db\Query;
$query = new Query();
$list = $query->select(['category_id', 'category_name'])
->from('product_category')
->where(['level' => 1, 'is_delete' => 0])
->all();
(3)事务处理
// 自动事务
Yii::$app->db->transaction(function () {
$user = new User();
$user->name = 'test';
$user->save();
});
// 手动事务
$transaction = Yii::$app->db->beginTransaction();
try {
// 业务逻辑
$transaction->commit();
} catch (\Exception $e) {
$transaction->rollBack();
throw $e;
}
三、Laravel 与 Yii 2 数据库操作核心差异
| 对比维度 | Laravel | Yii 2 |
|---|---|---|
| 核心操作方式 | 1. 主推 Eloquent ORM(面向对象)2. 支持 DB 门面(无模型快捷操作)3. 原生 SQL 需通过 DB::select 执行 | 1. 主推 Active Record(模型驱动)2. 支持 Query 类(无模型,语法繁琐)3. 原生 SQL 需通过 createCommand 执行 |
| 模型依赖与创建 | 1. Eloquent 模型手动创建,继承 Model 类2. 支持无模型操作,灵活度高 | 1. AR 模型推荐通过 Gii 生成,继承 ActiveRecord 类2. 强依赖模型,无官方无模型快捷方式 |
| 查询结果转数组 | 后置方法 toArray(),需在查询结果后调用 |
前置方法 asArray(),查询时指定返回格式 |
| 批量赋值控制 | 强制配置 $fillable/$guarded,否则抛异常,安全性高 |
通过 rules() 验证规则间接控制,无专门属性,需手动把控 |
| 关联模型定义 | 关联方法名直接映射属性(如 orders() 对应 $user->orders) |
关联方法需以 getXXX() 命名(如 getOrders()) |
| 分页功能 | 一键生成:paginate(10),视图直接渲染分页链接 |
需借助 ActiveDataProvider 配置实现完整分页 |
| 查询缓存 | 无内置机制,需手动结合 Cache 门面实现 | 内置缓存:cache(3600) 方法快速启用 |
| 适用场景 | 中小型项目、快速开发,适合新手和追求优雅语法的团队 | 中大型项目、高性能需求,适合需精细控制的团队 |
四、Laravel 与 Yii 2 语法逐行对照表
基于相同业务场景编写,方便跨框架快速切换复制。
| 业务场景 | Laravel 语法 | Yii 2 语法 |
|---|---|---|
| 查询所有数据 | // Eloquent 方式 use App\Models\User; $users = User::all()->toArray(); / DB 门面方式 use Illuminate\Support\Facades\DB; $users = DB::table('users')->get()->toArray(); |
// AR 方式 use app\models\User; $users = User::find()->asArray()->all(); // Query 方式 use yii\db\Query; $query = new Query(); $users = $query->from('users')->all(); |
| 按主键查单条数据 | use App\Models\User; $user = User::find(1)->toArray(); $user = User::findOrFail(1)->toArray(); |
use app\models\User; $user = User::findOne(1, ['asArray' => true]); $user = User::find()->where(['id'=>1])->asArray()->one(); |
| 多条件查询 | use App\Models\User; $users = User::where('status', 1)->where('age', '>', 18)->orderBy('id', 'desc')->get()->toArray(); |
use app\models\User; $users = User::find()->where(['status'=>1])->andWhere(['>', 'age', 18])->orderBy(['id'=>SORT_DESC])->asArray()->all(); |
| 关联查询(用户-订单,一对多) | // User 模型定义关联 public function orders(){ return $this->hasMany(Order::class); } // 预加载查询 $user = User::with('orders')->find(1); $orders = $user->orders->toArray(); |
// User 模型定义关联 public function getOrders(){ return $this->hasMany(Order::class, 'user_id'); } // 预加载查询 $user = User::find()->with('orders')->where(['id'=>1])->one(); $orders = $user->orders; |
| 新增数据 | use App\Models\User; // 单条新增 User::create(['name'=>'test', 'email'=>'test@xxx.com']); // 批量新增 User::insert([ ['name'=>'test1'],['name'=>'test2']]); |
use app\models\User; // 单条新增 $user = new User(); $user->name = 'test'; $user->save(); // 批量新增 Yii::$app->db->createCommand()->batchInsert( 'users',['name'],[['test1'],['test2']])->execute(); |
| 批量更新 | use App\Models\User; User::where('status', 1)->update(['status'=>2]); |
use app\models\User; User::updateAll(['status'=>2], ['status'=>1]); |
| 原生 SQL 执行 | use Illuminate\Support\Facades\DB; // 查询 $users = DB::select('select * from users where id = ?', [1]); // 执行更新 DB::statement('update users set status=1 where id=1'); |
// 查询 $users = Yii::$app->db->createCommand( 'select * from users where id=:id',[':id'=>1])->queryAll(); // 执行更新 Yii::$app->db->createCommand( 'update users set status=1 where id=1')->execute(); |
五、常见错误对比排查表
| 错误现象 | Laravel 可能原因及解决方案 | Yii 2 可能原因及解决方案 |
|---|---|---|
| 批量赋值失败 | 未配置 $fillable/$guarded,在模型中添加对应字段即可 |
未配置 rules() 验证规则,或字段无写入权限,补充规则或检查字段权限 |
| 查询结果无法转数组 | 忘记调用 toArray(),或查询结果为单条对象,需先判断再转换 |
未添加 asArray() 方法,或查询方式错误,在 find() 后添加该方法 |
| 关联查询出现 N+1 问题 | 未使用 with() 预加载关联,改为 User::with('orders')->get() |
同 Laravel,需通过 with() 预加载,避免循环中查询关联 |
| 模型找不到对应表 | 表名不符合默认复数规则,在模型中手动配置 $table 指定表名 |
未实现tableName() 方法,或方法返回表名错误,补充该方法并校验表名 |
| 事务提交/回滚失败 | 数据库引擎不支持事务(如 MyISAM),改为 InnoDB;或未捕获异常 | 未实例化 $transaction 对象,或引擎不支持,检查引擎并规范事务写法 |
| 分页功能无法正常显示 | 未在视图中调用 $users->links(),补充分页链接渲染代码 |
未使用 ActiveDataProvider 配置分页,改用数据提供器实现 |


