2013-02-25 102 views
3

我一直試圖在laravel的雄辯中創建我自己的可鏈接方法,但我錯過了一些東西,不知道是什麼。這可能聽起來有點瘋狂,但看看我的功能,以更好地瞭解我想說什麼。在laravel中創建一個可鏈接的方法

class Post extends Eloquent{ 
    public static function custom_wh($data){ 
     return static::where_in('categories_id', $data, 'AND'); 
    } 
} 

//this works fine 
$posts = Post::custom_wh(array(1, 2, 3))->get(); 

//but this says custom_wh is not defined in the query class 
$posts = Post::where_in('tags', array(2, 3, 4), 'AND')->custom_wh(array(1, 2, 3))->get(); 

如果我理解正確,那麼我的方法沒有資格鏈接另一種方法?所以我想我的問題是我如何在我的模型中創建一個可鏈接的方法?

PS我已經看了一下laravel的查詢生成器類,在那裏我已經看到,可鏈式方法返回該對象的實例,但我找不到方法來返回對象,而不是我在上面的代碼。任何形式的建議或建議都非常感謝。提前致謝。

回答

8

由於您的問題,Laravel提供這樣的一種新的方式,被稱爲 「查詢範圍」。你可以找到文檔here

你只需要編寫一個函數的前綴scope,你就能鏈像其他查詢生成器的人這個方法:

class Post extends Eloquent { 

    public function scopeWhereCategories($query, $categories) 
    { 
     return $query->whereIn('categories_id', $categories, 'AND'); 
    } 

} 

$posts = Post::whereCategories(array(1, 2, 3))->get(); 
$posts = Post::orderBy('date')->whereCategories(array(1, 2, 3))->take(5)->get(); 
+0

喜歡這個功能,並且已經在使用它了:D我知道這個在我發佈我的問題時並不存在,但我選擇這個作爲像我這樣的其他Google搜索的正確答案。謝謝。 – 2014-01-14 13:50:26

0

不知道,如果我是正確的,但是這是我想出了快...

郵政:: where_in()沒有返回雄辯的模型,它返回類型的查詢對象。

對於如何簡單你寫你的自定義功能,我只想避免從我頭頂的功能

$posts = Post::where_in('tags', array(2, 3, 4))->where_in('categories_ids', array(1,2,3))->get(); 

你可以嘗試像

class Post extends Eloquent { 
    public static function custom_wh($data=array()) { 
     return static::where_in('categories_id', $data); 
     // return type of query not eloquent 
    } 
} 

$posts = Post::custom_wh(array(1,2,3))->where_in('tags', array(2, 3, 4))->get(); 

,除非你想改變查詢類

+0

好,這就是我所做的和它的作品,但問題是custom_wh函數是不可鏈式的,所以假設我有一個巨大的查詢需要進行多次連接,因此我想將它們包裝在單獨的函數中,並在需要時將它們鏈接起來,然後出現問題。我試圖將它們放入函數的另一個原因是ORM不應該是我的模型嗎?而且我也試圖讓我的代碼「幹」。 – 2013-02-26 08:05:11

0

您是否嘗試過使用'se如果'而不是'靜態'?據我所知,如果你使用self和屬性/方法,並且你的子類和你引用的方法不覆蓋主類屬性/方法,它將返回,在這種情況下,方法'where_in '的查詢類。然後你將能夠鏈接你自定義的方法。

11

好的......這可能會扭曲你的大腦,但堅持我。實際定義的方法是_where()。那麼Post :: where和$ post->如何最終調用_where()方法?答案是'魔術'。 :D

PHP有這些東西被稱爲'魔術方法',使一些非常動態的行爲。在這種情況下,Laravel正在使用__callStatic()和__call()來處理對未定義方法的調用。這使得相同的方法被靜態和非靜態地調用。

public static function __callStatic($method, $parameters) 
{ 
    // Create a new instance of the called class, in this case it is Post 
    $model = get_called_class(); 

    // Call the requested method on the newly created object 
    return call_user_func_array(array(new $model, $method), $parameters); 
} 

所以基本上Post :: where()只是$ post = new Post的簡寫; $ post-> where()

從這裏請求到__call(),其中有一個下劃線方法名稱的數組。如果請求的方法位於下劃線名稱列表中,則調用並返回$ this - > _ method()。

但這仍然不是全部。德魯是正確的,'where_in'返回一個查詢對象。大多數您熟悉的ORM鏈接方法實際上都是ORM Query對象的一部分。這是整個過程。

  • 後::在哪裏(...)
  • 後:: __ callStatic( '其中',...)
  • $崗位 - > __通話( '其中',...)
  • $查詢 - > _調用( '其中',...)
  • $查詢 - > _其中(...)

要擴展的類是由查詢使用模型。無法向__call()中定義的下劃線方法列表添加另一個方法名稱。您必須將__call()全部複製到您的查詢定義中,以便使您的新方法具有該行爲。

我已經在我的項目中完成了這項工作,將指向Eloquent(Laravel模型的別名)的擴展版本,使我的所有模型都可以使用擴展的Query方法。

// application/libraries/mylib/query.php 
namespace MyLib; 

class Model extends \Laravel\Model { 

    // Tell \MyLib\Model to use \MyLib\Query instead of Laravels Query 
    protected function query() 
    { 
     return new \MyLib\Query($this); 
    } 

} 

// application/libraries/mylib/query.php 
namespace MyLib; 

class Query extends \Laravel\Database\Eloquent\Query { 

    function _my_method() { ... } 

    function __call() { ... } 
} 

// application/config/application.php 
'aliases' => array(
    ... 
    'Eloquent' => 'MyLib\\Model', 
    ... 
) 

http://php.net/manual/en/language.oop5.magic.php https://github.com/laravel/laravel/blob/master/laravel/database/eloquent/model.php#L734 https://github.com/laravel/laravel/blob/master/laravel/database/eloquent/query.php#L274

+0

,這解釋了很多。說實話我沒有研究太多的OO在PHP和我開始使用框架,因爲我認爲我會學習面向對象,因爲我走,所以是這是非常有一個抓地力,但萊米一槍在它使用你的技術。如果我還有其他問題,我會通知你。非常感謝您的幫助。 – 2013-03-03 15:41:24