首頁 >後端開發 >php教程 >巧妙的重載魔術方法__call()

巧妙的重載魔術方法__call()

WBOY
WBOY原創
2016-08-08 09:31:24852瀏覽

工作半年了,感覺這半年學到的東西比大學四年學到的還要多,主要原因是心靜下來了,目標也明確了,不會去整天的和遊戲糾纏在一起了。大學時候其實也意識到了玩遊戲會影響自己的正常學習和工作的,但是一直控制不了自己,還是忍不住經常去玩,沒日沒夜的玩(本來就是悶騷男,還宅著玩遊戲,這也是大學四年只有遊戲、左右手,沒有女朋友的原因了)。現在工作了,每天都有任務,看到旁邊的牛人們在專案中如魚得水,就有了趕超他們的想法,於是每天都會給自己一個額外的小任務去學習新的知識,到現在工作有半年了,對以前不熟悉的linux現在也可應熟悉的使用了,對不熟悉的js也有了新的認識,可以說現在我對工作可以勝任(如果分為新手、高級新手、勝任者、精通者、專家)了,開發過活動、介面、後台,也優化完善過系統的框架,只要是產品運作提出的合理需求都可以快速的支援到位。當然還確確實實的感受到一點:程式設計師真是個奇怪的群體,大多時候總是會覺得自己的點子是最好的。 當然這個算是自信但有時候討論的時候你的咄咄逼人不一定是好事,所以還要多聽聽其他人的想法,不但可以發現自己的不足,還會建立良好的:」友誼「。跟大家瞎扯了這麼多這半年的一點點感受,謝謝你可以堅持看完^_^。

下面步入真題,說說如何巧妙的運用php的魔術方法,我相信這個在大多數項目中會用到。

先說明一下,這個小技巧我在專案中已經有很好的應用了,給我們專案帶來了很大的方便,在這裡先賣賣關子,您不妨繼續往下看。

在專案中,可配的設定資訊一定大量存在,比如說一個遊戲的機器人開放時段、支付方式的開啟與否、商城顯示title的配置等等,這些配置資訊一般有一個特點就是沒有特定的規則,而且產品運作可以隨時的給據實際情況去修改,這些資訊怎麼保存呢,肯定不會每種類型都去建一張表,這樣做簡直就是費力不討好,你想下,也許一張表中就保存了一條信息,所以得想想其他的方法,雖然這些信息沒有規則,但是他們卻有一個特點就是不會有太多,而且一般情況下數組就可以保存所有需要配置的信息,因此用json字符字串儲存資訊是個不錯的選擇,當需要使用的時候直接取出json_decode這樣就可以直接使用了,下面看看具體怎麼巧妙的利用php的魔術方法實現的。

這裡你先要了解下php的一個魔術方法__call(),查下php官方的文檔,是這樣解釋這個函數的

<span>public</span> <span>mixed</span> __call ( <span>string</span> <span>$name</span> , <span>array</span> <span>$arguments</span><span> )

__call() is triggered when invoking inaccessible methods in an </span><span>object</span> context.

意思是說當在一個物件中呼叫一個不可存取的方法(沒有權限、不存在)時會觸發這個函數,函數的參數$name是呼叫的函名,$arguments是呼叫的函數參數陣列。看看下面這個範例:

<span>class</span><span> Test
{
    </span><span>public</span> <span>function</span> __call(<span>$name</span>, <span>$arguments</span><span>)
    {
        </span><span>echo</span> "你调用了一个不存在的方法:\r"<span>;
        </span><span>echo</span> "函数名:{<span>$name</span>}\r"<span>;
        </span><span>echo</span> "参数: \r"<span>;
        </span><span>print_r</span>(<span>$arguments</span><span>);
    }
}

</span><span>$T</span> = <span>new</span><span> Test();
</span><span>$T</span>->setrobottime("12", "18");

這個函數會輸出下面的結果

<span>你调用了一个不存在的方法:
函数名:setrobottime
参数: 
Array
(
    [</span>0] => 12<span>
    [</span>1] => 18<span>
)</span>

這樣,我們就可以不去直接定義函數,而是用這個特性去做一些事情了。下面看看程式碼的實作思路,主要是思路,其中有些我是假設的,就像資料庫連接,這裡不主要講這個。

<span>class</span><span> Config
{
    </span><span>/*</span><span>*
     * 这里假定下数据库表名为
     * config.config,
     * 字段为:
     * config_key varchar(50),
     * config_value text,
     * primary key(config_key)
     *
     * 数据库连接为$link
     * 插入方法封装为query
     * 获取一条信息方法封装为getOne
     </span><span>*/</span>
    <span>/*</span><span>*
     * 要进行的操作
     </span><span>*/</span>
    <span>private</span> <span>static</span> <span>$keys</span> = <span>array</span><span>(
        </span><span>//</span><span>'调用方法' => 'key',</span>
        'roboottime'    => 'ROBOOTTIME',
        'dailysignin'   => 'DAILYSIGNIN',<span>
    );

    </span><span>/*</span><span>*
     * 设置方法
     * @param string $config_key 配置项key
     * @param string $config_value 配置型内容(一般为json格式)
     * @returne boolen true/false 插入是否成功
     </span><span>*/</span>
    <span>private</span> <span>function</span> set(<span>$config_key</span>, <span>$config_value</span><span>){
        </span><span>$sql</span> = "insert into config.config (config_key,config_value) values ('{<span>$config_key</span>}','{<span>$config_value</span>}') on duplicate key update config_value='{<span>$config_value</span>}'"<span>;
        </span><span>return</span> <span>$link</span>->query(<span>$sql</span><span>);
    }

    </span><span>/*</span><span>*
     * 获取值的方法
     * @param $config_key 要获取的配置的key
     * @returne string/false json字符串/失败
     </span><span>*/</span>
    <span>private</span> <span>function</span> get(<span>$config_key</span><span>)
    {
        </span><span>$sql</span> = "select * from config.config where config_key='{<span>$config_key</span>}'"<span>;
        </span><span>if</span>(<span>$ret</span> = <span>$link</span>->getOne(<span>$sql</span>,<span> MYSQL_ASSOC)){
            </span><span>return</span> <span>$ret</span><span>;
        }
        </span><span>return</span> <span>false</span><span>;
    }

    </span><span>/*</span><span>*
     * 重载魔术方法
     * @param string $name 被调用的方法名
     * @param array $arguments 调用时传递的参数
     * @return mixed 返回结果
     </span><span>*/</span>
    <span>public</span> <span>function</span> __call(<span>$name</span>, <span>$arguments</span><span>)
    {
        </span><span>$act</span>    = <span>substr</span>(<span>$name</span>, 0, 3<span>);
        </span><span>$func</span>   = <span>substr</span>(<span>$name</span>, 3<span>);
        </span><span>if</span>(!<span>in_array</span>(<span>$func</span>, self::<span>$keys</span><span>)){
            </span><span>return</span> <span>false</span><span>;
        }
        </span><span>if</span>(<span>$act</span> == 'set'<span>)
        {
            </span><span>return</span> <span>$this</span>->set(self::[<span>$func</span>], <span>$arguments</span>[0<span>]);
        }
        </span><span>elseif</span>(<span>$act</span> == 'get'<span>)
        {
            </span><span>return</span> <span>$this</span>->get(self::[<span>$func</span><span>]);
        }
        </span><span>return</span> <span>false</span><span>;
    }
}</span>

這樣,我們的就可以透過一張表儲存多個資訊了,呼叫時也很方便,只需要擴充下Config::$keys數組中的資訊就可以了,這樣做只是為了規範,為了可以清晰的知道哪些配置存放在了這張表中。

使用的時候可以像這樣去存放和獲取

<span>$config</span> = <span>new</span><span> Config();

</span><span>$info</span> = <span>array</span>("12","20"<span>);

</span><span>//</span><span>设置</span>
<span>$config</span>->setroboottime(json_encode(<span>$info</span><span>));

</span><span>//</span><span>获取</span>
<span>$config</span>->getroboottime();

這裡再說一個要注意的點,這些配置信息一般會緩存到redis中,放在數據庫中只是為了防止redis掛掉之後從數據庫中去恢復,這裡的一般指的是那些經常去讀取的信息,為了減少和db的交互,直接放在快取中。

  本文版權歸作者iforever(luluyrt@163.com)所有,未經作者本人同意禁止任何形式的轉載,轉載文章之後必須在文章頁面明顯位置給出作者和原文連接,否則保留追究法律責任的權利。

posted @ 2015-01-10 12:23 奔跑的Man 閱讀(...) 評論(...) 編輯 收藏

刷新評論刷新頁面返回頂部

博客園首頁博問新聞閃存程式設計師招募知識庫

公告

Copyright ©2015 奔跑的Man

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn