模型【 Eloquent】
什么是模型
这是一个对象关系映射器(ORM),使与数据库的交互变得很愉快。使用 Eloquent 时,每个数据库表都有一个对应的「模型」,用于与该表进行交互。除了从数据库表中检索记录外,Eloquent 模型还允许您从表中插入,更新和删除记录。
需要注意的是模型默认使用类的复数形式来作为表名。比如User的模型,表明为users。
如果表是以 _ 连接的,则需要通过 大驼峰命名 方式来命名模型。例如:表user_infos 的模型名称为 UserInfo。
模型的创建
php artisan make:model User
生成的模型会被安放在 app/Models 目录下。
模型的属性
1.table 表名称
就跟我上面说的一样,模型默认使用用类的复数形式作为表明,所以如果有必要可以指定表名。
protected $table = 'my_tablename';
2.timestamps 时间戳
模型默认相应的数据库表中存在 created_at 和 updated_at 字段。在创建或更新模型时,Eloquent 将自动设置这些字段的值。如果你的表中不存在,可以将它关闭。
public $timestamps = false;
3.primaryKey 主键
模型默认主键为ID。也可以自己指定。
protected $primaryKey = 'your_parmaryKey';
4.fillable 允许放行的字段【可以理解为:白名单】
Product 模型代码:
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
use HasFactory;
protected $table='product';
public $timestamps=false;
protected $fillable=[
'name'
];
}
这个属性只有这批量新增的时候才有效。新增单挑无效。
5.guarded 不允许放行字段【可以理解为:黑名单】
和上面的 fillable 一样的效果,只不过一个允许一个不允许。
6.attributes 默认值
新增数据时如果没有指定该字段的值,则会启用默认值。
基本操作
1.新增方法
create 多条
save 单条
注意:
在使用 create 方法之前,你需要在你的模型类上指定一个 fillable 或 guarded 属性。 这些属性是必需的,因为默认情况下,所有 Eloquent 模型都受到保护,免受批量赋值漏洞的影响。
2.修改方法
save
update
3.删除方法
5.查询方法
#get
roduct::where('id','>',2)->get();
#find
Product::find(1);
软删除
在实际项目中,对数据频繁使用删除操作会导致性能问题,软删除的作用就是
把数据加上删除标记,而不是真正的删除,同时也便于需要的时候进行数据的恢
复。在模型中添加 Illuminate\Database\Eloquent\SoftDeletes 。同时如果你数据表中没有deleted_at【数据类型:datetime】字段,需要把 deleted_at 字段添加到数据表中。
开始删除数据
Product::destroy([2,4]);
查询软删除数据
onlyTrashed 方法 - 只查询软删除的数据;
withTrashed 方法 - 查询包括软删除在内的所有数据;
Product::onlyTrashed();
恢复软删除 restore
Product::where('id',4)->restore();
永久删除 forceDelete
$pro=Product::onlyTrashed(2);
$pro->forceDelete();
获取器和修改器
获取器
获取到模型实例后,通过模型实例去获取某个字段的数据时触发获取器。该方法必须为public类型。方法命名规范为:getFieldNameAttribute。
模型:
public function getSexAttribute($value){
if($value==1){
return '男';
}
return '女';
}
控制器:
public function index(){
$res=Product::find(4);
dump($res->sex);
}
修改器
在修改某个字段数据的时候进行触发。
修改器方法的命名规范为:setFieldNamexAttribute。
public function setSexAttribute($value){
if($value=='男'){
return $this->attributes['sex']=1;
}
return $this->attributes['sex']=0;
}
Product::create(["name"=>'修改器',"sex"=>'男']);
事件
创建事件
php artisan make:event 事件名称
该文件会存放在 app/Events 目录下面。
生成监听器
php artisan make:listener 监听器名称
该文件会存放在 app/Listeners 目录下面。
注册:
事件和监听器在创建完毕后,还需要将二者联合起来。我们可以在
EventServiceProvider 服务提供者中进行注册。如下:
protected $listen = [
事件名称 => [
监听器名称,
.
.
.
],
];
测试:
监听器文件:
激活事件:
访问:
模型事件
触发方式 | |
---|---|
retrieved | 获取到模型实例后触发 |
creating | 插入到数据库前触发 |
created | 插入到数据库后触发 |
updating | 更新到数据库前触发 |
updated | 更新到数据库后触发 |
saving | 保存到数据库前触发(插入/更新之前,无论插入还是更新都会触发) |
saved | 保存到数据库后触发(插入/更新之后,无论插入还是更新都会触发) |
deleting | 从数据库删除记录前触发 |
deleted | 从数据库删除记录后触发 |
restoring | 恢复软删除记录前触发 |
restored | 恢复软删除记录后触发 |
测试:
模型文件:
控制器:
随着业务的增加,监听器越来越多,我们要一一注册实现这样比较麻烦浪费时间。这时候可以考虑用观察者。
观察者
观察者的创建
php artisan make:observer ProductObserver
#创建时与模型进行关联
php artisan make:observer ProductObserver --model=Product
文件默认存放在 App\Observers 目录下
注册
① App\Providers\AppServiceProvider.php
②在模型文件中加入:
protected static function booted()
{
self::observe(ProductObserver::class);
}
上面2种方式都可以完成注册。
测试
观察者文件:
访问【新增数据】:
访问【更新数据】:
这种方法只有更新成功才能触发,受影响行数要大于0.这是我测试的结果,如果有这结论不对还请指出。
模型关联
表 | test_id 与test 表ID的对应关系 |
---|---|
test_info | 一对一 |
test_phone | 多对一 |
开始前先确定三个模型对应的表和timestamps;如果没有updated_at这种字段要将timestamps设为false。
protected $table=yourtable;
public $timestamps=false;
一对一
hasOne(related,foreign_key,local_key)
related: 关联的模型
foreign_key:关联模型的key【默认:模型_id】
local_key: 主键 【默认id】
test模型:
public function testinfo(){
return $this->hasOne(TestInfo::class,'test_id','id');
}
test控制器:
<?php
namespace App\Http\Controllers;
use App\Models\Product;
use App\Models\Test;
use App\Models\TestInfo;
class TestController
{
public function Index(){
$res=Test::find(1);
dump($res->testinfo);
}
}
先在test表里查出ID为1的数据,再去test_info中根据模型的关联,查出test_id=1的数据。
在一对一关系中,如果我们需要一次性查询出 10 个 test 并带上对应的testInfo 的话,那么就需要给数据库打 1 + 10 条 SQL,这样性能是很差的。
public function Index(){
$res=Test::all(); #查询全部数据
foreach($res as $rs){ #遍历取出对应test_info数据
$rs->testinfo;
}
}
所以我们可以用预加载with 方法来进行查询。
Test::with('TestInfo')->get();
这样一对比性能明显就提上去了。
一对多
test模型:
public function testphone(){
return $this->hasMany(TestPhone::class);
}
从上面的图可以看出来查出了3条数据。