搜尋

首頁  >  問答  >  主體

thinkphp 程式碼復用的問題

用ThinkPhp3.2做開發,因為很多時候要用到增刪改查操作,為了增加程式碼的複用。我在common寫了一個curdControler和curdModel做程式碼的增刪改查,需要用到增刪改查時直接繼承curdController和curdModel。

現在有一個問題一般curd操作都要做權限的判斷,否則會很危險。我這裡的思路是在curdController構造方法中調用一個checkAuth();因為各種功能,權限控制的方法會有不同,怎麼強制繼承curdController的子類必須重載checkAuth方法了?

我的想法是,我把權限判斷函數 定義為抽象方法

protected abstract function checkAuth()

類別curdController定義為抽象類別,但是抽象類別不能被實例化那麼建構函式的程式碼是不是就無效了,這樣實作有什麼不妥

第二問題,大家在做tp的程式碼重用時,有什麼更好的思路,我這種做法有什麼隱患和問題了,謝謝指教.

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){

    }
代言代言2699 天前1051

全部回覆(1)我來回復

  • typecho

    typecho2017-07-01 09:13:50

    程式碼重複使用,我建議用PHP的特性:
    http://php.net/manual/zh/lang...
    或用閉包綁定(不太建議):
    http://php.net /manual/en/clos...

    checkAuth可以透過不同的業務,書寫不同的traits,在具體繼承curdController的類別中使用對應的traits,由於checkAuth()只返回校驗結果的真假,所以這個可以向任意的Controller中客製化checkAuth()

    針對你的第一個問題,由於你在繼承了抽象類別curdController的子類別建構子裡,手動呼叫了parent::__construct();,只要子類別被實例化,父類別的建構函數也是可以用的,看下面範例:
    程式碼:

    <?php
    abstract class A
    {
        public function __construct()
        {
            echo '父类';
        }
    }
    
    class B extends A
    {
        public function __construct()
        {
            parent::__construct();
            echo '子类';
        }
    }
    
    $test = new B();

    結果:

    針對你第二個問題,個人覺得整個結構框架有些粗,對於常見的一對多和多對多關係仍然需要手動去做,建議將這種關聯操作也封裝起來。

    雖然我個人用的比較多的框架是CodeIgniter,但是我覺得MVC(HMVC)模型基本思路都是一致的,所以下面談下我個人在CodeIgniter裡做的重用封裝:

    我個人將資料表的原子操作放在了底層Model上面(是基於CI-Base-Model改的,你可以看一下CI-Base-Model裡的has_many配置),另外我繼承了CI-Base-Model自己寫了一個CRUD_Model,這個CRUD_Model中,幾乎靠一些配置項和一些重寫,就可以快速生成一個標準CRUD數組,下面可以放出部分原始碼:

    <?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)
        {
            // 删除
            ...
        }
    }

    我這個模型的思路希望可以對你細化CRUD邏輯有所幫助。

    回覆
    0
  • 取消回覆