227 lines
5.3 KiB
PHP
227 lines
5.3 KiB
PHP
<?php
|
||
|
||
namespace App\Models;
|
||
|
||
use Illuminate\Database\Eloquent\Model;
|
||
|
||
class BaseModel extends Model
|
||
{
|
||
// 自定义时间戳字段
|
||
const CREATED_AT = 'create_time';
|
||
const UPDATED_AT = 'update_time';
|
||
|
||
/**
|
||
* 是否启用系统字段自动维护
|
||
* 包括:tenant_id、creator、create_time、updater、update_time、deleted
|
||
* 默认关闭,需要的模型可以设置为true
|
||
*/
|
||
protected $enableSystemFields = false;
|
||
|
||
/**
|
||
* 是否启用租户隔离
|
||
* 默认关闭,需要的模型可以设置为true
|
||
*/
|
||
protected $enableTenantScope = false;
|
||
|
||
/**
|
||
* 序列化日期为指定格式
|
||
*/
|
||
protected function serializeDate(\DateTimeInterface $date): string
|
||
{
|
||
return $date->format('Y-m-d H:i:s');
|
||
}
|
||
|
||
/**
|
||
* 查询作用域:未删除
|
||
*/
|
||
public function scopeNotDeleted($query)
|
||
{
|
||
return $query->where('deleted', 0);
|
||
}
|
||
|
||
/**
|
||
* 查询作用域:当前租户
|
||
*/
|
||
public function scopeCurrentTenant($query)
|
||
{
|
||
$tenantId = $this->getCurrentTenantId();
|
||
if ($tenantId !== null) {
|
||
return $query->where('tenant_id', $tenantId);
|
||
}
|
||
return $query;
|
||
}
|
||
|
||
/**
|
||
* 查询作用域:启用状态
|
||
*/
|
||
public function scopeActive($query)
|
||
{
|
||
return $query->where('status', 1);
|
||
}
|
||
|
||
/**
|
||
* 查询作用域:排序
|
||
*/
|
||
public function scopeOrdered($query)
|
||
{
|
||
return $query->orderBy('sort', 'asc')->orderBy('id', 'desc');
|
||
}
|
||
|
||
/**
|
||
* 查询作用域:安全查询(未删除 + 当前租户)
|
||
*/
|
||
public function scopeSafeQuery($query)
|
||
{
|
||
return $query->notDeleted()->currentTenant();
|
||
}
|
||
|
||
/**
|
||
* 获取当前租户ID
|
||
*/
|
||
protected function getCurrentTenantId(): ?int
|
||
{
|
||
$user = auth('admin')->user();
|
||
return $user ? $user->tenant_id : null;
|
||
}
|
||
|
||
/**
|
||
* 软删除(将deleted字段设置为1)
|
||
*/
|
||
public function delete()
|
||
{
|
||
if ($this->enableSystemFields) {
|
||
return $this->update(['deleted' => 1]);
|
||
}
|
||
|
||
return parent::delete();
|
||
}
|
||
|
||
/**
|
||
* 强制删除(真正删除记录)
|
||
*/
|
||
public function forceDelete()
|
||
{
|
||
return parent::delete();
|
||
}
|
||
|
||
/**
|
||
* 恢复软删除的记录
|
||
*/
|
||
public function restore()
|
||
{
|
||
if ($this->enableSystemFields) {
|
||
return $this->update(['deleted' => 0]);
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 查询包含已删除记录的作用域
|
||
*/
|
||
public function scopeWithDeleted($query)
|
||
{
|
||
return $query->withoutGlobalScope('not_deleted');
|
||
}
|
||
|
||
/**
|
||
* 只查询已删除记录的作用域
|
||
*/
|
||
public function scopeOnlyDeleted($query)
|
||
{
|
||
return $query->withoutGlobalScope('not_deleted')->where('deleted', 1);
|
||
}
|
||
|
||
/**
|
||
* 设置系统字段(创建时)
|
||
*/
|
||
public function setCreateFields(): void
|
||
{
|
||
if (!$this->enableSystemFields) {
|
||
return;
|
||
}
|
||
|
||
$userId = auth('admin')->id() ?? 0;
|
||
$tenantId = $this->getCurrentTenantId() ?? 0;
|
||
|
||
$this->creator = $userId;
|
||
$this->create_time = now();
|
||
$this->tenant_id = $tenantId;
|
||
$this->deleted = 0;
|
||
}
|
||
|
||
/**
|
||
* 设置系统字段(更新时)
|
||
*/
|
||
public function setUpdateFields(): void
|
||
{
|
||
if (!$this->enableSystemFields) {
|
||
return;
|
||
}
|
||
|
||
$userId = auth('admin')->id() ?? 0;
|
||
|
||
$this->updater = $userId;
|
||
$this->update_time = now();
|
||
}
|
||
|
||
/**
|
||
* 验证租户权限
|
||
*/
|
||
public function validateTenantAccess(): bool
|
||
{
|
||
$currentTenantId = $this->getCurrentTenantId();
|
||
|
||
// 如果当前用户没有租户ID,不允许访问
|
||
if ($currentTenantId === null) {
|
||
return false;
|
||
}
|
||
|
||
// 如果记录没有租户ID,不允许访问
|
||
if (!isset($this->tenant_id)) {
|
||
return false;
|
||
}
|
||
|
||
// 验证租户ID是否匹配
|
||
return $this->tenant_id == $currentTenantId;
|
||
}
|
||
|
||
/**
|
||
* 保存前的钩子
|
||
*/
|
||
protected static function booted()
|
||
{
|
||
$model = new static;
|
||
|
||
// 只有启用系统字段维护的模型才自动设置系统字段
|
||
if ($model->enableSystemFields) {
|
||
// 创建时自动设置系统字段
|
||
static::creating(function ($model) {
|
||
$model->setCreateFields();
|
||
});
|
||
|
||
// 更新时自动设置系统字段
|
||
static::updating(function ($model) {
|
||
$model->setUpdateFields();
|
||
});
|
||
|
||
// 全局作用域:自动过滤已删除数据
|
||
static::addGlobalScope('not_deleted', function ($builder) {
|
||
$builder->where('deleted', 0);
|
||
});
|
||
}
|
||
|
||
// 只有启用租户隔离的模型才添加租户作用域
|
||
if ($model->enableTenantScope) {
|
||
// 全局作用域:自动过滤租户数据
|
||
static::addGlobalScope('tenant', function ($builder) {
|
||
$model = new static;
|
||
$tenantId = $model->getCurrentTenantId();
|
||
if ($tenantId !== null) {
|
||
$builder->where('tenant_id', $tenantId);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
}
|