2013-10-01 60 views
0

我有一個users和一個orders表。用戶可以有很多訂單,並且訂單屬於用戶。Laravel 4雄辯約束

Users 
id | name | email 

Orders 
id | user_id | name 

所以我的用戶模型如下:

class User extends Eloquent{ 
    public function orders(){ 
     return $this->hasMany('Order', 'user_id'); 
    } 
} 

我的訂單模式:

class Order extends Eloquent{ 
    public function user(){ 
     return $this->belongsTo('User', 'user_id'); 
    } 
} 

現在,我有一個順序控制器,將列出訂單在數據庫中。我想根據GET變量列出訂單。

如:www.domain.com/order?user=some+name
www.domain.com/order?name=order+name

對於第二個,我能做到以下幾點:

$orders = Order::with('user')->where('name', 'LIKE', '%'.Input::get('name') . '%')->get();

但第一個,下面的代碼失敗:

$orders = Order::with('user')->where('user.name', 'LIKE', '%' . Input::get('user') . '%')->get();

我有也試過這樣:

$orders = Order::with(array('user' => function($q){ 
    $q->where('name', 'LIKE', '%' . Input::get('user') . '%'); 
    }))->get(); 

用戶的姓名是否與GET字符串匹配與否這一個返回所有訂單。

那麼,有沒有辦法用口才能達到上述目的呢?手動加入是唯一的方法嗎?

+1

據我所知,在當前版本中,不能使用細節表過濾器過濾主表。您將使用原始SQL或Fluent編寫該代碼。 –

回答

2

編輯基於提問者備註:說了這麼多,你可能需要訪問多個基於過濾器/搜索的表格字段。這是實現它的一種方法。

在你Order.php模型,做這樣的事情:

public function scopeOrdersByQuery($query, $userName, $orderName) 
{ 
    $query->leftJoin('users', 'users.id', '=', 'orders.user_id') 
     ->select(array('orders.*', DB::raw('users.name as user_name'), DB::raw('users.id as uid'))); 

    if (!empty($userName)) 
    { 
     $query = $query->whereIn('users.user_name', $userName); 
    } 

    if (!empty($orderName)) 
    { 
     $query = $query->whereIn('orders.name', $orderName); 
    } 
} 

添加更多的表連接的需要。

在你OrdersController做這樣的事情:

$userName = Input::get('userName'); 
$orderName = Input::get('orderName'); 

$orders = Order::ordersByQuery($userName, $orderName)->get(); 

現在,您可以顯示所有的訂單,或者搜索基於多個查詢或只有一個。沒有測試,但應該工作。

------------ ------------編輯

我想,如果你想獲得的所有訂單爲特定用戶使用的用戶ID 。

在您的訂單。PHP的模式,這樣做:

public static function getOrdersByUserId($userId) 
{ 
    $orders = Order::with('user')->whereIn('user_id', $userId)->get(); 

    return $orders; 
} 

然後,您可以通過這種方法,特定的用戶ID你後你OrdersController這樣做:現在

$userId = Input::get('user'); 

$orders = Order::getOrdersByUserId($userId); 

,這是假設在你看來,你是將用戶標識添加到名爲'user'的輸入值。

您還可以擴展getOrdersByUserId()方法,通過在Orders.php模型使用範圍的方法,以適應空白$ userId的值,就像這樣:

public function scopeGetOrdersByUserId($query, $userId) 
{ 
    $query->with('user'); 

    if(!empty($userId)) 
    { 
     $query = $query->whereIn('user_id', $userId); 
    } 
} 
在你的控制器

現在,這樣做:

$userId = Input::get('user'); 

$orders = Order::getOrdersByUserId($userId)->get(); 
// if paginating do $orders = Order::getOrdersByUserId($userId)->paginate(10); 

這樣做可以讓您在OrdersController的索引方法中使用此代碼,從而允許您在提供ID時顯示所有訂單或特定用戶訂單。

編輯:有一件事我忘了提的是,生成表單的時候,在你的控制器做:

$users = User::orderBy('name')->lists('name', 'id'); 

那麼這個變量傳遞到您的視圖,並用它來填充你的用戶選擇框。我假設你正在使用選擇框來選擇用戶。

編輯:正如@GladToHelp指出的那樣,您可能希望使用Eager Load Constraints將約束添加到急切加載的模型。您可以通過在你的Orders.php模型中使用修改getOrdersByUserId()方法的範圍這樣做用戶名,而不是:

public function scopeGetOrdersByUserName($query, $userName) 
{ 
    $query->with(array('user' => function($query2) 
    { 
     $query2->where('name', 'like', '%$userName%'); 
    })); 
} 

注意:這是未經測試的代碼。

這就是說,你可能想簡單地使用:

$user = User::with('orders')->where('name', $name)->get(); 

然後使用foreach循環在視圖上$用戶>訂單。

+0

我想他不想通過user_id過濾它們。他希望過濾用戶名由查詢字符串傳遞的訂單。你可以看到user.name字段是users表的一部分,所以你不能只說:Order :: with('user') - > whereIn('user_id',$ userId) - > get(); –

+0

@GladToHelp是的,我明白,隊友,但正如我在我的回答中所說,我會使用用戶名而不是用戶名來獲得訂單。查詢字符串不僅看起來更整齊,而且仍然允許他在選擇框中顯示用戶名,但提交的值將是用戶ID。說實話,我們不知道他是如何傳遞查詢字符串的。 –

+0

我同意這一點。傳遞一個ID而不是用戶名是一種更好的方法,但是恐怕Laravel本身的根本問題會稍微深入一些。看起來Eloquent不容易根據目前急切加載的模型上的約束來過濾主要模型。 –

0

所以我結束了使用連接如下:

$orders = Order::with('user') 
      ->join('users', 'users.id', '=', 'orders.user_id') 
      ->where('users.name', 'LIKE', '%' . Input::get('name') . '%')->get(); 

上面的例子看起來不錯,因爲我只參加兩個型號/表。但在我真正的應用程序中,我有5個模型,我急於與訂單,它確實混淆,與表列名稱衝突和所有。

希望有一個更簡單的方法來做它的雄辯。

+0

看我上面的編輯,看看這是否對你有幫助。 –