laravel orm
laravel 使用 orm 調用數據庫查詢的時候很方便,我們只需要配置完數據庫連接後創建model。
比如我們查詢用戶,我們首先要有一個user model
。
可以使用 artisan
創建
php artisan make:model userModel
如果我們需要查詢一個用戶信息,只需要這樣
userModel::where('id', 1)->first();
(new userModel)->where('id', 1)->first();
上面的兩種方法都可以實現查詢用戶id爲1的用戶信息。那他們有什麼區別呢?第一種方法更爲優雅。
那這個是怎麼實現的呢,一般我們要麼定義一個靜態方法用來靜態調用,要麼定義一個對象方法需要使用對象調用。
其實很簡單,他只是用到了php
的魔術方法
。
來看一下下面兩個魔術方法:
- __call()
- __callStatic()
看一下php文檔中的介紹
__call()
在對象中調用一個不可訪問方法時,__call() 會被調用。
public __call ( string $name , array $arguments ) : mixed
__callStatic()
在靜態上下文中調用一個不可訪問方法時,__callStatic() 會被調用。
public static __callStatic ( string $name , array $arguments ) : mixed
arguments 參數是一個枚舉數組,包含着要傳遞給方法 $name 的參數。
我們要讓一個對象方法可以靜態調用就要通過__callStatic()
魔術方法了。
public static function __callStatic( string $name , array $arguments) {
return (new static)->$name(...$arguments);
}
這樣的話當我們調用userModel::where()
的時候實際上它內部會創建一個對象然後再對象調用where
。
但是這樣會產生一個問題,如果當我們調用的方法不存在的時候怎麼辦呢。
可以通過try catch
來捕獲錯誤進行錯誤處理。laravel內部就是這麼實現的。在laravel的model文件下,是這麼運用__call()
的。
/**
* Handle dynamic method calls into the model.
*
* @param string $method
* @param array $parameters
* @return mixed
*/
public function __call($method, $parameters)
{
if (in_array($method, ['increment', 'decrement'])) {
return $this->$method(...$parameters);
}
return $this->forwardCallTo($this->newQuery(), $method, $parameters);
}
他裏面調用了forwardCallTo
方法,我們來看一下這個方法。
這個方法存在ForwardsCalls
這個trait
中。
/**
* Forward a method call to the given object.
*
* @param mixed $object
* @param string $method
* @param array $parameters
* @return mixed
*
* @throws \BadMethodCallException
*/
protected function forwardCallTo($object, $method, $parameters)
{
try {
return $object->{$method}(...$parameters);
} catch (Error | BadMethodCallException $e) {
$pattern = '~^Call to undefined method (?P<class>[^:]+)::(?P<method>[^\(]+)\(\)$~';
if (!preg_match($pattern, $e->getMessage(), $matches)) {
throw $e;
}
if ($matches['class'] != get_class($object) ||
$matches['method'] != $method) {
throw $e;
}
static::throwBadMethodCallException($method);
}
}
他在調用的時候通過try catch來捕獲錯誤。
還有另外一種方法同樣可以判斷這個類有沒有這個方法,那就是先通過get_class_methods($className)
這個函數獲取到類的所有方法,然後我們就可以自己判斷了。
public function __call($method, $parameters)
{
$classFuns = get_class_methods($this);
if (!in_array($method, $classFuns)) {
return "沒有這個方法"; //返回錯誤
}
return $this->$method(...$parameters);
}
這樣也不失爲一種方法啊,大家還有其他好方法的話歡迎交流。