likeadmin php 版 ,想加一个机构表institution,然后给每个管理员绑定一个机构 Id(institution_id),每个机构管理登录只能看到该机构下的信息,基层代码或者中间件代码还有公共代码怎么改造啊,请写的详细一点,每段代码带上文件名和代码注释

likeadmin php 版 ,想加一个机构表institution,然后给每个管理员绑定一个机构 Id(institution_id),每个机构管理登录只能看到该机构下的信息,基层代码或者中间件代码还有公共代码怎么改造啊,请写的详细一点,每段代码带上文件名和代码注释
用户545179374
01月09日
|
浏览 76

解决方案:为 LikeAdmin PHP 添加机构隔离功能

1. 数据库改造

文件名: database/migrations/2024_01_01_000000_add_institution_to_admins.php

复制代码
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AddInstitutionToAdmins extends Migration
{
    /**
     * 为管理员表添加机构字段
     */
    public function up()
    {
        // 1. 创建机构表
        Schema::create('institution', function (Blueprint $table) {
            $table->id();
            $table->string('name', 100)->comment('机构名称');
            $table->string('code', 50)->unique()->comment('机构编码');
            $table->tinyInteger('status')->default(1)->comment('状态 1启用 0禁用');
            $table->timestamps();
            $table->softDeletes();
        });
        
        // 2. 为管理员表添加机构ID字段
        Schema::table('admin', function (Blueprint $table) {
            $table->unsignedBigInteger('institution_id')->nullable()->after('id')->comment('机构ID');
            $table->foreign('institution_id')->references('id')->on('institution')->onDelete('set null');
        });
        
        // 3. 为需要隔离的数据表添加机构ID字段(以user表为例)
        Schema::table('user', function (Blueprint $table) {
            $table->unsignedBigInteger('institution_id')->nullable()->after('id')->comment('机构ID');
            $table->index('institution_id'); // 添加索引提高查询效率
        });
    }
}

2. 模型层改造

文件名: app/models/Admin.php

复制代码
<?php
namespace app\models;

use think\Model;

class Admin extends Model
{
    /**
     * 关联机构
     */
    public function institution()
    {
        return $this->belongsTo(Institution::class, 'institution_id');
    }
    
    /**
     * 获取当前管理员的机构ID
     */
    public function getInstitutionId()
    {
        return $this->institution_id ?? 0;
    }
}

文件名: app/models/Institution.php

复制代码
<?php
namespace app\models;

use think\Model;

class Institution extends Model
{
    protected $name = 'institution';
    
    /**
     * 关联管理员
     */
    public function admins()
    {
        return $this->hasMany(Admin::class, 'institution_id');
    }
}

3. 中间件实现机构隔离

文件名: app/middleware/InstitutionAuth.php

复制代码
<?php
namespace app\middleware;

use think\facade\Db;
use think\facade\Request;

class InstitutionAuth
{
    /**
     * 机构权限验证中间件
     */
    public function handle($request, \Closure $next)
    {
        // 获取当前登录管理员
        $adminId = session('admin_id');
        if (!$adminId) {
            return json(['code' => 401, 'msg' => '未登录']);
        }
        
        // 查询管理员所属机构
        $admin = Db::name('admin')->where('id', $adminId)->find();
        $institutionId = $admin['institution_id'] ?? 0;
        
        // 超级管理员(institution_id为0或null)拥有全部权限
        if (empty($institutionId)) {
            $request->institutionId = null; // 不限制机构
            return $next($request);
        }
        
        // 将机构ID注入到请求对象中
        $request->institutionId = $institutionId;
        
        // 验证机构状态是否正常
        $institution = Db::name('institution')
            ->where('id', $institutionId)
            ->where('status', 1)
            ->find();
            
        if (!$institution) {
            return json(['code' => 403, 'msg' => '机构已被禁用或不存在']);
        }
        
        return $next($request);
    }
}

4. 服务层添加机构查询作用域

文件名: app/common/InstitutionScope.php

复制代码
<?php
namespace app\common;

use think\facade\Request;

class InstitutionScope
{
    /**
     * 自动添加机构查询条件
     * @param \think\db\Query $query
     * @param string $field 机构ID字段名,默认为institution_id
     */
    public static function apply($query, $field = 'institution_id')
    {
        $institutionId = Request::instance()->institutionId ?? null;
        
        // 如果请求中没有机构ID(超级管理员),不添加限制
        if ($institutionId === null) {
            return;
        }
        
        // 普通管理员:只查询本机构数据
        $query->where($field, $institutionId);
    }
}

5. 控制器基类改造

文件名: app/controller/AdminBase.php

复制代码
<?php
namespace app\controller;

use app\common\InstitutionScope;
use think\facade\Request;

class AdminBase extends BaseController
{
    /**
     * 初始化方法
     */
    protected function initialize()
    {
        parent::initialize();
        
        // 获取当前机构ID
        $this->institutionId = Request::instance()->institutionId;
    }
    
    /**
     * 获取带机构限制的查询构造器
     * @param string $model 模型名
     * @param string $field 机构字段名
     */
    protected function buildInstitutionQuery($model, $field = 'institution_id')
    {
        $query = Db::name($model);
        InstitutionScope::apply($query, $field);
        return $query;
    }
    
    /**
     * 验证数据是否属于当前机构
     * @param string $table 表名
     * @param int $id 数据ID
     */
    protected function checkInstitutionPermission($table, $id)
    {
        if ($this->institutionId === null) {
            return true; // 超级管理员跳过验证
        }
        
        $data = Db::name($table)
            ->where('id', $id)
            ->where('institution_id', $this->institutionId)
            ->find();
            
        return !empty($data);
    }
}

6. 路由配置

文件名: route/admin.php

复制代码
<?php
use think\facade\Route;

// 需要机构隔离的路由组
Route::group('admin', function () {
    // 用户管理
    Route::get('user/list', 'admin.User/index');
    Route::post('user/add', 'admin.User/add');
    Route::put('user/edit/:id', 'admin.User/edit');
    Route::delete('user/del/:id', 'admin.User/del');
    // ... 其他需要隔离的路由
})->middleware([
    app\middleware\CheckAdminLogin::class,
    app\middleware\InstitutionAuth::class  // 添加机构验证中间件
]);

7. 业务控制器示例

文件名: app/controller/admin/User.php

复制代码
<?php
namespace app\controller\admin;

class User extends AdminBase
{
    /**
     * 用户列表(自动机构隔离)
     */
    public function index()
    {
        $page = input('page', 1);
        $limit = input('limit', 20);
        
        // 使用基类方法构建查询
        $query = $this->buildInstitutionQuery('user');
        
        // 添加其他查询条件
        if ($keyword = input('keyword')) {
            $query->whereLike('username|mobile', "%{$keyword}%");
        }
        
        $list = $query->paginate($limit, false, ['page' => $page]);
        
        return json([
            'code' => 1,
            'data' => $list->items(),
            'count' => $list->total()
        ]);
    }
    
    /**
     * 编辑用户(机构权限验证)
     */
    public function edit($id)
    {
        // 验证数据权限
        if (!$this->checkInstitutionPermission('user', $id)) {
            return json(['code' => 0, 'msg' => '无权操作该数据']);
        }
        
        // ... 编辑逻辑
    }
}

8. 视图层改造(如果需要)

文件名: app/view/admin/layout.html

复制代码
<!-- 在侧边栏或顶部显示当前机构 -->
<div class="institution-info">
    <span>当前机构:{{$admin.institution.name|default='超级管理员'}}</span>
</div>

实施步骤:

  1. 执行数据库迁移:php think migrate:run
  2. 在管理员管理页面添加机构分配功能
  3. 为现有管理员分配机构ID(超级管理员设为NULL)
  4. 逐步为需要隔离的数据表添加institution_id字段
  5. 在对应的控制器中应用机构查询作用域

如需继续排查,请点击下方【🔍追问按钮】提交补充信息

我要提问
复制内容
分享给好友
AI编程问答网 免责声明:
以上内容除特别注明外均来源于网友提问,AI编程问答网回答,权益归原著者所有;