自動判斷應該Ajax還是return

2021-09-07 06:50:17 字數 3164 閱讀 8015

最近回顧以前的**,發現乙個偶爾會見到的現象。乙個類裡面的方法可能需要ajax返回,也有可能需要函式return。這個現象發生在**mvc中的 邏輯層(或模型層),示例如下。indexctrl是控制器負責渲染頁面,proctrl是邏輯器負責讀取處理資料,a函式是例項化乙個類,m函式是讀取資料表的意思。現在只是簡單的頁面輸出。

class indexctrl extends

ctrl

}class proctrl extends

ctrl

}

現在來了乙個管理後台中,需要用ajax獲取這些首頁產品列表。怎麼改呢?直接再加乙個 function getlistajax(); 然後讀取同樣的資料庫,做同樣的操作?這顯然不科學,同樣的邏輯不應該被實現兩次。

那就定義乙個函式 getlistajax() 裡面呼叫自身的 getlist() 然後再ajax返回。這樣看起來似乎也沒太大問題,但是當這種類似的場景增多的時候,豈不是所有的方法都有乙個ajax的副本?

這樣的話,就應該對 getlist 函式進行改造了。怎麼改呢? 加乙個可選引數 $isreturn 預設值為false,此時為ajax請求返回json;呼叫者呼叫時傳入引數值為true,函式進行return。**如下:

class indexctrl extends

ctrl

}class proctrl extends

ctrl

else}}

這樣的話,基本上實現了乙個函式可以同時擁有兩種返回方式,一種是ajax,一種是函式return。但是這存在很多明顯的問題:

1、需要修改呼叫者,呼叫者需要傳遞引數true才能實現函式返回;

2、如果該函式本身就有引數,那加上這個附加引數就會顯得很臃腫。

3、不自動,基本屬於重複手寫狀態。

根據觀察到的現象,我們發現這裡判斷的關鍵是 $isreturn 變數,這個變數是true還是false到底有沒有辦法做到自動識別呢?那麼自動識別的前提是什麼呢?根據專案的實際情況,我定出了規則 ,就是直接訪問這個方法的url(如http://localhost/pro/getlist)則使用ajax返回,訪問其它url則使用函式return

那怎麼做呢?專案中使用的是thinkphp框架,它裡面有幾個預定義魔法常量 module_name,controller_name,action_name,分別表示當前訪問的模組名(home、admin、mobile等)、控制器名、操作名。而php原生也有幾個魔法常量,__class__、__function__表示當前訪問的類名和方法名。所以只要判斷 模組名+控制器名==類名、操作名==方法名,就可以得出是url直接訪問的,使用ajax返回,否則使用return。**如下:

class proctrl extends

ctrl

else}}

這樣就完了嗎?當然不是,這麼長的乙個判斷總不能每個都複製一遍吧,肯定要把它封裝起來成為乙個公共函式。這個封裝看起來很簡單嘛,直接弄去乙個函式裡就完了。然而,too native!因為php的這兩個魔術常量是會變的。當你把這段**抽到乙個函式中時(例 isnowaction() ),__class__ 就變成了空字串,__function__ 就變成了 'isnowaction' 。好吧,既然普通函式不行,那有沒有別的方法呢?

一、c語言中有乙個叫做「內聯函式」的概念,就是說這個函式雖然是寫出來了,但是編譯的時候是把它作為呼叫者的一部分直接編譯到該函式中,而普通函式是通過返回跳轉的(如彙編指令 ret 、 jmp)。所以,按理說這樣的話這兩個魔術常量就會像預期一樣得出我們想要的值。然而,php裡面並沒有內聯函式這個東西,並沒有 inline 關鍵字 。。。

二、一技不成又生一技,有乙個東西就做「巨集定義」。c語言裡面很多時候是用來封裝乙個小函式的,比如  #define pyth(x,y) sqrt(x*x+y*y) ,可以這樣用來巨集定義乙個函式,或者說是簡寫乙個函式。所以我也按照這樣的方式寫了乙個(用了匿名函式,這很js)

define('isnowaction()', function

()else

});

但是發現這個並沒有成功執行。翻了一下php的文件才知道這php的define並不能定義函式

還真不得不說,有時候特性太少真是乙個麻煩事啊。難道這樣就沒有辦法了嗎?在函式里設兩個引數,讓呼叫者把__class__和__function__傳過來?但這樣的封裝只是聊勝於無,並不理想。或者可以這樣想,既然沒有辦法定義特殊的函式,那能不能有辦法在函式裡翻出呼叫者的資訊呢?

功夫不負,還真有!有乙個函式名為debug_backtrace(),可以找到呼叫者的資訊。如圖中紅色箭頭所指, 這個陣列的第二項中的function和class正是呼叫者的函式名和類名。

封裝好的函式**如下:

//

是否為當前模組下的控制器下的方法,常用於判斷是return還是ajax

function

isnowaction()

else

}

當然還可以直接封裝到邏輯層ctrl基類中,作為乙個基礎方法

class

ctrl

else}}

這樣的話 proctrl 可以非常簡潔,而又能自動判斷是應該ajax返回還是return

class proctrl extends

ctrl

}

本來以為,這個函式到此為止就算是結束了。然而並沒有。為什麼呢?繼承的問題。比如 admin模組裡的 proctrl類的getlist()方法 繼承自home中的proctrl類,那麼debug_backtrace() 得出來的 class 的類名將會是 home\proctrl,也就是得到的是父類的名字而不是自己的名字,這個問題用 __class__ 魔法變數也是一樣存在。不知這個算不算是php語言的乙個bug呢?

class

ctrl

else}}

萬萬沒想到,想要實現乙個如此基礎的自動化功能,扯出了這麼多一堆概念和技術,從c語言、彙編到php再到物件的問題,中間還有類似js的影子。

json解析時自動判斷是object還是array

參考 jsonobject.getstring 解析任意欄位均可強轉為string json解析時自動判斷是object還是array 解析json時遇到的問題,返回的json內容中可能為jsonarray,也可能是jsonobject,當只有乙個資訊時是jsonobject,有多個資訊時是json...

json解析時自動判斷是object還是array

最近解析json時遇到的問題,返回的json內容中可能為jsonarray,也可能是jsonobject,當只有乙個資訊時是jsonobject,有多個資訊時是jsonarray,如果去修改json的返回格式有些不現實。通過字元判斷的話又很麻煩。解決方案 通過jsontokener解析,jsonto...

PHP自動判斷測試環境還是生產環境

由測試環境發布到生產環境要修改一些配置引數,該來該去挺麻煩還容易出錯。可以在nginx中配置乙個環境引數fastcgi param run env dev 來做判斷 php中判斷載入哪個配置檔案 define run env isset server run env server run env p...