thinkphp code reuse problem
代言
代言 2017-07-01 09:11:50
0
1
1076

Use ThinkPhp3.2 for development, because many times you need to use addition, deletion, modification, and search operations in order to increase code reuse. I wrote a curdControler and curdModel in common to do the addition, deletion, modification and query of the code. When I need to use the addition, deletion, modification and query, I directly inherit curdController and curdModel.

Now there is a problem. Generally, curd operation requires permission judgment, otherwise it will be very dangerous. My idea here is to call a checkAuth() in the curdController construction method; because of various functions, the permission control methods will be different. How to force subclasses that inherit curdController to overload the checkAuth method?

My idea is that I define the permission judgment function as an abstract method

protected abstract function checkAuth()

The class curdController is defined as an abstract class, but if the abstract class cannot be instantiated, then the code of the constructor will be invalid. What is wrong with this implementation?

Second question, do you have any better ideas when reusing TP code? What are the hidden dangers and problems of my approach? Thank you for your advice.

class CurdController extends Controller
{
    //基础curd类必须进行权限判断,否则会造成很大的问题
    public function __construct()
    {
        parent::__construct();
        $this->checkAuth();
    }

    //存储模型对象
    protected  $_model;
    //权限判断函数
    protected function checkAuth(){}
    //列表处理函数
    public function listC(){
//      列表前置函数
        $this->beforeList();
        $data=$this->_model->lists();
        $this->assign('lists',$data);
        $this->display();
    }

    public function delC(){
        $id=intval(I('get.id'));
        $where['id']=$id;
        $res=$this->_model->del($where);
        $this->redirectUrl($res,'listC');
    }

    public function addC(){
//        添加前置函数
        $this->beforeAdd();
        if(IS_POST){
            $data=I('post.');
            $res=$this->_model->Store($data);
            $this->redirectUrl($res,'listC');
        }
        $this->display();
    }

    public function editC(){
        $id=intval(I('get.id'));
        //where的数组形式
        $where['id']=$id;
//        编辑前置函数
        $this->beforeEdit($where);
        if(IS_POST){
            $where=I('post.');
            $where['id']=$id;
            $res=$this->_model->Store($where);
            $this->redirectUrl($res,'listC');
        }
        $this->display();
    }
    //列表前置操作
    protected function beforeList(){

    }
    /**
     * 添加控制器前置操作
     */
    protected function beforeAdd(){

    }

    /**
     * 编辑控制器前置操作
     * @param $where
     */
    protected function beforeEdit($where){

    }
代言
代言

reply all(1)
typecho

For code reuse, I recommend using PHP features:
http://php.net/manual/zh/lang...
Or use closure binding (not recommended):
http://php.net /manual/en/clos...

checkAuthYou can write different traits through different businesses, and use the corresponding traits in the class that specifically inherits curdController. Since checkAuth() only returns the true or false of the verification result, this can be applied to any Controller Customize checkAuth().

In response to your first question, since you manually called parent::__construct(); in the constructor of the subclass that inherited the abstract class curdController, as long as the subclass is instantiated, the construction of the parent class Functions can also be used, see the example below:
Code:

<?php
abstract class A
{
    public function __construct()
    {
        echo '父类';
    }
}

class B extends A
{
    public function __construct()
    {
        parent::__construct();
        echo '子类';
    }
}

$test = new B();

Result:

In response to your second question, I personally feel that the entire structural framework is a bit rough. Common one-to-many and many-to-many relationships still need to be done manually. It is recommended to encapsulate this association operation.

Although the framework I personally use more often is CodeIgniter, I think the basic ideas of the MVC (HMVC) model are the same, so let’s talk about the reuse encapsulation I personally made in CodeIgniter:

I personally put the atomic operations of the data table on the bottom layer Model (based on CI-Base-Model, you can take a look at has_many and belongs_to in CI-Base-Model Configuration), and I inherited CI-Base-Model and wrote a CRUD_Model myself. In this CRUD_Model, almost relying on some configuration items and some rewriting, I can quickly generate a standard CRUD array, which can be released below Part of the source code:

<?php
/**
 * @uses array_helper
 */
class CRUD_Model extends CI_Base_Model
{
    public $ci;

    public $crud_total = 0;

    private $crud_offset = 0;
    private $crud_page   = 0;
    private $crud_limit  = 20;

    protected $crud_mask = [];

    public $crud_id         = [];
    public $crud_user_id    = 0;
    public $crud_time       = 0;
    public $crud_time_str   = '';
    public $crud_error_code = 0;
    public $crud_has_error  = FALSE;

    public function __construct()
    {
        parent::__construct();
        $this->ci = &get_instance();
    }

    /**
     * ---------------------------------------------------------
     * CRUD Block-separated Methods
     * CRUD 子功能方法
     * ---------------------------------------------------------
     */
    public function crud_paginator($offset = NULL, $page = NULL, $limit = 20)
    {
        // 解析分页参数的方法
        ...
    }

    public function crud_set_error($error_code = 0)
    {
        // 设置错误码(用于API或者Controller判定)和错误标记的方法
        $this->crud_has_error  = TRUE;
        $this->crud_error_code = $error_code;
    }

    protected function crud_process_id($id = 0, $data = [])
    {
        // 处理ID并缓存的方法
        ...
    }

    protected function crud_prepare($data = [])
    {
        // 准备数据(时间戳之类后面需要用到但和主体关系不大的数据)的方法
        $this->crud_time     = time();
        $this->crud_time_str = date('Y-m-d H:i:s', $this->crud_time);
    }

    protected function crud_filter_fields($data = [])
    {
        // 添加和修改时,过滤原数据中不需要的字段的方法
        ...
    }

    protected function crud_save_total($data = [])
    {
        // 查询加上过滤条件后的总条数的方法
        $this->select("''");
        $this->crud_total = $this->count_all_results();
    }

    protected function crud_add_list_filter($data = [])
    {
        // 列表筛选条件过滤方法
    }

    protected function crud_add_detail_filter($data = [])
    {
        // 详情筛选条件过滤方法
    }

    protected function crud_add_fields($data = [])
    {
        // 列表和详情字段附加方法(SELECT子句)
    }

    protected function crud_add_limit()
    {
        // 条数限制(分页过滤器)方法
        if($this->crud_limit !== 'all') {
            $this->limit($this->crud_limit, $this->crud_offset);
        }
    }

    protected function crud_add_order($data = [])
    {
        // 排序附加方法
    }

    protected function crud_add_list_with($data = [])
    {
        // 列表with(CI-Base-Model中额外添加数据的绑定钩子)的附加方法
    }

    protected function crud_add_detail_with($data = [])
    {
        // 详情with的附加方法
    }

    protected function crud_build_item($item = [])
    {
        // 对列表和详情字段进行处理的方法(直接取出来默认是字符串,如果是数字型需要手动转)
        return $item;
    }

    protected function crud_build_proto($data = [])
    {
        // 构造列表分页输出结构的方法,这个之后会向这个数组再附加列表list值
        $proto = [];
        $proto['total']  = ...;
        $proto['offset'] = ...;
        $proto['page']   = ...;
        $proto['is_last_page'] = ...;
        $proto['is_full_page'] = ...;

        return $proto;
    }

    protected function crud_detail_precheck($detail = [])
    {
        // 详情预检查方法
        return TRUE;
    }

    protected function crud_detail_postcheck($detail = [])
    {
        // 详情后期检查方法
        return TRUE;
    }

    protected function crud_insert_precheck($data = [])
    {
        // 新增预检查方法
        return TRUE;
    }

    protected function crud_insert_postcheck($data = [])
    {
        // 新增后期检查方法
        return TRUE;
    }

    protected function crud_update_precheck($data = [])
    {
        // 更新预检查方法
        return TRUE;
    }

    protected function crud_update_postcheck($data = [])
    {
        // 更新后期检查方法
        return TRUE;
    }

    protected function crud_delete_precheck($data = [])
    {
        // 删除预检查方法
        return TRUE;
    }

    protected function crud_delete_postcheck($data = [])
    {
        // 删除后期检查方法
        return TRUE;
    }

    protected function crud_insert_rebuild($data = [])
    {
        // 新增数据时重新构造传入数据的方法(使其符合数据库结构)
        return [];
    }

    protected function crud_update_rebuild($data = [])
    {
        // 更新数据时重新构造传入数据的方法
        return [];
    }

    /**
     * ---------------------------------------------------------
     * CRUD Main Methods
     * CRUD 主要函数
     * ---------------------------------------------------------
     */
    protected function crud_list($offset = NULL, $page = NULL, $limit = 20, $data = [])
    {
        // 查询列表
        ...
    }

    protected function crud_detail($id = 0, $data = [])
    {
        // 查询详情
        ...
    }

    protected function crud_insert($data = [])
    {
        // 添加
        ...
    }

    protected function update_feed($id = 0, $data = [])
    {
        // 修改
        ...
    }

    protected function crud_delete($id = 0)
    {
        // 删除
        ...
    }
}

I hope the idea of ​​​​my model can help you refine CRUD logic.

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template