代码之家  ›  专栏  ›  技术社区  ›  WebNovice

Laravel 4雄辩约束

  •  0
  • WebNovice  · 技术社区  · 12 年前

    我有一个 users 和一个 orders 桌子一个用户可以有多个订单,并且一个订单属于一个用户。

    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字符串匹配,此命令都会返回所有订单。

    那么,我是不是没有办法雄辩地实现上述目标呢?手动JOIN是唯一的方法吗?

    3 回复  |  直到 12 年前
        1
  •  2
  •   Gareth Daine    12 年前

    根据提问者的评论进行编辑 :如上所述,您可能需要基于筛选器/搜索访问多个表字段。以下是实现这一目标的一种方法。

    在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。

    在Order.php模型中,执行以下操作:

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

    然后,您可以通过在OrdersController中执行此操作,将您想要的特定用户id传递给此方法:

    $userId = Input::get('user');
    
    $orders = Order::getOrdersByUserId($userId);
    

    现在,这是假设在您的视图中,您正在将一个用户id添加到名为“user”的输入的值中。

    您还可以通过在Orders.php模型中使用scope方法来扩展getOrdersByUserId()方法,以容纳空白的$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所指出的那样,您可能希望使用Eagle 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();
    

    然后在$user->上的视图中使用foreach循环;订单。

        2
  •  1
  •   Glad To Help    12 年前

    这是最接近您需要的:扩展模型

     public function newQuery($excludeDeleted = true){
            return parent::newQuery()->join('table','field1','=','field2');
        }
    

    更多信息请点击此处: http://forums.laravel.io/viewtopic.php?pid=56659#p56659

        3
  •  0
  •   WebNovice    12 年前

    因此,我最终使用了如下JOIN:

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

    上面的例子看起来不错,因为我只连接了两个模型/表。但在我的实际应用程序中,我有5个模型是用Order加载的,而且它确实会让人感到困惑,因为表列名冲突等等。

    希望在Eloquent中有一种更简单的方法。