php類連貫操作(類似thinkphp數據庫連貫操作)的實現原理

2016-10-18 1452 0 編輯:深色多郎 來源:程序網頁設計

如果你是一名使用過多種框架的php程序員,你一定見過這樣的查詢語句:

查看代碼打印

$result = $mysqlDb->limit(’0,10′)->order('id desc')->select();

上面的查詢語句,連續使用->操作符進行操作,并最終返回一個查詢結果,那么這是如何實現的呢。

我們來簡單分析一下:

-> 操作符用來訪問對象,上面的語句一共使用了3次 -> 操作符,而最后一次返回的是查詢結果,這說明,前2次 -> 訪問后,返回的應該是一個對象,因為在php中,如果你對一個非對象使用->操作符是不可能的。這告訴我們,$mysql實例中的limit和order方法都返 回一個對其所在類自身的引用即 return $this,了解了這一點,那么我們就可以實現連貫查詢了。示例代碼如下:

查看代碼打印

<?php

header('Content-type:text/html;charset=utf-8');

/*

*類功能:實現數據庫的連貫查詢操作

*/

class mysql_query{

    var $tbl='user';//要操作的表名

    var $limit='';//存儲limit語句的變量

    var $order='';//存儲order語句的變量

    var $sql='';//存儲完整sql語句的變量

    function limit($str) {

        $this->limit='limit '.$str;//設置limit語句

        //返回對類自身的引用,這里不能使用return new mysql_qery(),

        //因為這樣相當于又創建了類的一個新實例,那么上一步設置的limit語句,在新實例中是不存在的

        //大家可以自己實驗

        //因此要返回$this,即當前類的實例

        return $this;

    }    

    function order($str) {

        $this->order='order by '.$str;//設置order語句

        return $this;//返回對類自身的引用

    }

    function findall() {

        $this->sql='select * from '.$this->tbl.' '.$this->order.' '.$this->limit;//拼接sql語句

        echo $this->sql;//輸出,由于是示例,所以沒有寫查詢數據庫的代碼

    }

}

//示例

$mysqlDb=new mysql_query();

$result = $mysqlDb->order('id desc')->limit('0,10')->findall();

print_r($result);

另外也有框架是使用 __call() 這個魔術方法來實現的,如:

查看代碼打印

<?php

class Test {

    protected $options = array();

    //這里就是了, 通過判斷調用的函數名, 如果存在, 那么設置參數, 返回自己

    public function __call($func, $args) {

        if (in_array($func, array('form', 'field', 'join', 'order', 'where', 'limit', '更多....'))) {

            $this->options[$func] = $args;

            return $this; //這里返回了本對象

        }

    }

}

//示例

$test = new Test();

$test->form('test'); //這樣調用就相當于設置 $test->options['form'] = 'test

在ThinkPHP中的連貫查詢操作基本是以find,findAll或者select結尾的,所以前面這些方法的調用只是在設置查詢的參數而已,在find或者findAll方法中,是根據$this->options參數的不同執行不同的SQL,比如這樣:

查看代碼打印

public function find() {

    $sql = "SELECT {$this->options['field']} FROM {$this->options['form']}";

    $sql .= isset($this->options['where']) ? " WHERE {$this->options['where']}" : '';

    //.........更多處理

    echo $sql;

}

這里只是簡單的講解一下, 和官方可能有點出入,在ThinkPHP里, 很帥的方法基本上都在__call函數中實現的比如有topN(), byXXX();

在thinkphp的代碼文件 lib/think/core/model.class.php 文件里面(Model類)有這么一段代碼:

查看代碼打印

/**

 +----------------------------------------------------------

 * 利用__call方法實現一些特殊的Model方法

 +----------------------------------------------------------

 * @access public

 +----------------------------------------------------------

 * @param array $args 調用參數

 +----------------------------------------------------------

 * @return mixed

 +----------------------------------------------------------

 */

public function __call($method,$args) {

    if(in_array(strtolower($method),array('field','table','where','order','limit','page','alias','having','group','lock','distinct'),true)) {

        // 連貫操作的實現

        $this-&gt;options[strtolower($method)] =   $args[0];

        return $this;

    }elseif(in_array(strtolower($method),array('count','sum','min','max','avg'),true)){

        // 統計查詢的實現

        $field =  isset($args[0])?$args[0]:'*';

        return $this-&gt;getField(strtoupper($method).'('.$field.') AS tp_'.$method);

    }elseif(strtolower(substr($method,0,5))=='getby') {

        // 根據某個字段獲取記錄

        $field   =   parse_name(substr($method,5));

        $where[$field] =  $args[0];

        return $this-&gt;where($where)-&gt;find();

    }else{

        throw_exception(__CLASS__.':'.$method.L('_METHOD_NOT_EXIST_'));

        return;

    }

}

代碼的具體功能,我就不解釋了,第一可能我也解釋不清楚;第二自己去看一下里面的編程思想還是有很多值的學習的。

下面附一個完整的使用 __call 實現的連貫操作示例:

查看代碼打印

<?php

class db{

    protected $options = array();

    public function select(){

        $fields = $this->options['field'] ? $this->options['field'] : "*";

        $query = "select ".$fields." from ";

        $query .= $this->options['table']." where ";

        $query .= $this->options['where']." limit 0,";

        $query .= $this->options['limit']." order by ";

        $query .= $this->options['order'].";";;

        echo $query;

        //這里根據實際情況寫一些做數據庫操作的邏輯

    }

    public function __call($methods,$vars){

        $this->options[$methods] = $vars[0];

        return $this;//關鍵在這里是返回對象

    }

}

$db = new db();$db->table('users')->field('username,passwd')->limit('10')->where("username = phpernote.com")->select()->order("id ASC");

本站文章均為深正網站建設摘自權威資料,書籍,或網絡原創文章,如有版權糾紛或者違規問題,請即刻聯系我們刪除,我們歡迎您分享,引用和轉載,但謝絕直接搬磚和抄襲!感謝...
關注深正互聯
七星彩头尾