study-api-v2/app/Models/BaseModel.php

227 lines
5.3 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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);
}
});
}
}
}