【问题标题】:Laravel query multiple eloquent relationshipsLaravel 查询多个 eloquent 关系
【发布时间】:2014-10-31 21:11:26
【问题描述】:

您好,我正在尝试查询数据库中表之间的关系。快速浏览我的应用程序,我有userstasksprojectstasksstatuses 和优先级。目前我想返回 auth 用户项目及其客户端名称和状态名称,可以通过使用 db 表中的相关 id 来检索它们。

我几乎正确地返回了所有这些,例如,如果我用项目和客户查询 Auth 用户,我会返回正确的数据,我在 repo 中有我的查询,我让我的控制器使用它:

public function getUserProjectswithClients()
    {
        return \User::with(array('projects', 'projects.clients'))
                            ->find(Auth::user()->id); 
    }

用户控制器

public function profile() {
 //returning users projects
    $data["usersprojects"] = $usersprojects = $this->userrepo->getUserProjectswithClients();
//  return $usersprojects;
  if(Request::ajax())
            {
              // --- this part of the code is odd
              $html = View::make('projects.openprojects ', $data)->render();
              return Response::json(array('html' => $html));

              // ---
            } else {


              $data = array(
                 'usersprojects' => $usersprojects
              );

              return View::make('users.profile', $data);
            } 

}

个人资料视图

@foreach($usersprojects->projects as $project) 

{ $project->project_name }}
    @if(!is_null($project->clients)) 
        {{ $project->clients->client_name }}
    @endif
@endif

@endforeach

这很好,但是如果我扩展查询以包含另一个关系,则会失败,例如

public function getUserProjectswithClients()
    {

        return \User::with(array('projects', 'projects.clients', 'projects.statuses'))->find(Auth::user()->id); 
    }

我的 laravel 错误日志是这样的:

    Next exception 'Illuminate\Database\QueryException' with message 'SQLSTATE[42S22]:
 Column not found: 1054 Unknown column 'statuses.project_id' in 'where clause' 
(SQL: select * from `statuses` where `statuses`.`project_id` in (4, 5, 6, 7, 8, 9, 
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 
31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 
73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 
94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 
112, 113, 114))' in /media/sf_Sites/tempus/vendor/laravel/framework/src/Illuminate/Database/Connection.php:600
    Stack trace:

我不确定我是否在模型中正确设置了我的关系,因为查询返回一个未知列。我的关系如下:

项目.php

public function statuses() {
        return $this->hasOne('Status');
    }

状态.php

public function projects()
{
    return $this->hasOne('Project');
}

如果我将 project.php 更改为:

public function statuses() {
        return $this->belongsTo('Status');
    }

我得到的状态返回为空,所以我认为我的关系是错误的,但我不确定 Projects 如何与状态建立 one-to-one 关系,一次只能分配一个。状态也是如此,可以将状态分配给项目,但在状态表中不会保留任何记录。

我的状态表架构如下:

 id | user_id | name | date_created | date_updated

我的项目表是这样的:

 id | user_id | client_id | status_id | project_name | project_brief  

谁能帮我开始做这个?谢谢

更新

根据 Jarek 更改关系的指示,我知道收到以下错误:

[2014-09-07 15:39:30] production.ERROR: exception 'BadMethodCallException' 
with message 'Call to undefined method Illuminate\Database\Query\Builder::statuses()' in /media/sf_Sites/tempus/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php:2117
Stack trace:
#0 [internal function]: Illuminate\Database\Query\Builder->__call('statuses', Array)
#1 [internal function]: Illuminate\Database\Query\Builder->statuses()
#2 /media/sf_Sites/tempus/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(913): call_user_func_array(Array, Array)
#3 [internal function]: Illuminate\Database\Eloquent\Builder->__call('statuses', Array)
#4 [internal function]: Illuminate\Database\Eloquent\Builder->statuses()
#5 /media/sf_Sites/tempus/bootstrap/compiled.php(7423): call_user_func_array(Array, Array)
#6 /media/sf_Sites/tempus/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(498): Illuminate\Database\Eloquent\Model->__call('statuses', Array)
#7 /media/sf_Sites/tempus/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(498): Project->statuses()
#8 [internal function]: Illuminate\Database\Eloquent\Builder->Illuminate\Database\Eloquent\{closure}()
#9 /media/sf_Sites/tempus/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php(158): call_user_func(Object(Closure))
#10 /media/sf_Sites/tempus/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(499): Illuminate\Database\Eloquent\Relations\Relation::noConstraints(Object(Closure))
#11 /media/sf_Sites/tempus/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(469): Illuminate\Database\Eloquent\Builder->getRelation('statuses')
#12 /media/sf_Sites/tempus/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(449): Illuminate\Database\Eloquent\Builder->loadRelation(Array, 'statuses', Object(Closure))
#13 /media/sf_Sites/tempus/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(158): Illuminate\Database\Eloquent\Builder->eagerLoadRelations(Array)
#14 [internal function]: Illuminate\Database\Eloquent\Builder->get()
#15 /media/sf_Sites/tempus/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php(281): call_user_func_array(Array, Array)
#16 /media/sf_Sites/tempus/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php(103): Illuminate\Database\Eloquent\Relations\Relation->__call('get', Array)
#17 /media/sf_Sites/tempus/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php(103): Illuminate\Database\Eloquent\Relations\HasMany->get()
#18 /media/sf_Sites/tempus/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(480): Illuminate\Database\Eloquent\Relations\Relation->getEager()
#19 /media/sf_Sites/tempus/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(449): Illuminate\Database\Eloquent\Builder->loadRelation(Array, 'projects', Object(Closure))
#20 /media/sf_Sites/tempus/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(158): Illuminate\Database\Eloquent\Builder->eagerLoadRelations(Array)
#21 /media/sf_Sites/tempus/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(125): Illuminate\Database\Eloquent\Builder->get(Array)
#22 /media/sf_Sites/tempus/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(82): Illuminate\Database\Eloquent\Builder->first(Array)
#23 /media/sf_Sites/tempus/app/Acme/Repositories/DbProjectRepository.php(25): Illuminate\Database\Eloquent\Builder->find('1')
#24 /media/sf_Sites/tempus/app/controllers/UsersController.php(47): Acme\Repositories\DbProjectRepository->getUserProjectswithClients()
#25 [internal function]: UsersController->profile()
#26 /media/sf_Sites/tempus/vendor/laravel/framework/src/Illuminate/Routing/Controller.php(231): call_user_func_array(Array, Array)
#27 /media/sf_Sites/tempus/bootstrap/compiled.php(5784): Illuminate\Routing\Controller->callAction('profile', Array)
#28 /media/sf_Sites/tempus/bootstrap/compiled.php(5772): Illuminate\Routing\ControllerDispatcher->call(Object(UsersController), Object(Illuminate\Routing\Route), 'profile')
#29 /media/sf_Sites/tempus/bootstrap/compiled.php(4971): Illuminate\Routing\ControllerDispatcher->dispatch(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request), 'UsersController', 'profile')
#30 [internal function]: Illuminate\Routing\Router->Illuminate\Routing\{closure}()
#31 /media/sf_Sites/tempus/bootstrap/compiled.php(5330): call_user_func_array(Object(Closure), Array)
#32 /media/sf_Sites/tempus/bootstrap/compiled.php(4996): Illuminate\Routing\Route->run(Object(Illuminate\Http\Request))
#33 /media/sf_Sites/tempus/bootstrap/compiled.php(4984): Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request))
#34 /media/sf_Sites/tempus/bootstrap/compiled.php(717): Illuminate\Routing\Router->dispatch(Object(Illuminate\Http\Request))
#35 /media/sf_Sites/tempus/bootstrap/compiled.php(698): Illuminate\Foundation\Application->dispatch(Object(Illuminate\Http\Request))
#36 /media/sf_Sites/tempus/bootstrap/compiled.php(7706): Illuminate\Foundation\Application->handle(Object(Illuminate\Http\Request), 1, true)
#37 /media/sf_Sites/tempus/bootstrap/compiled.php(8309): Illuminate\Session\Middleware->handle(Object(Illuminate\Http\Request), 1, true)
#38 /media/sf_Sites/tempus/bootstrap/compiled.php(8256): Illuminate\Cookie\Queue->handle(Object(Illuminate\Http\Request), 1, true)
#39 /media/sf_Sites/tempus/bootstrap/compiled.php(10895): Illuminate\Cookie\Guard->handle(Object(Illuminate\Http\Request), 1, true)
#40 /media/sf_Sites/tempus/bootstrap/compiled.php(659): Stack\StackedHttpKernel->handle(Object(Illuminate\Http\Request))
#41 /media/sf_Sites/tempus/public/index.php(49): Illuminate\Foundation\Application->run()
#42 {main} [] []

编辑:

DbProjectRepository.php

<?php
 namespace Acme\Repositories;

use Project, Auth, Status, Client, Teams, Input, Task;


class DbProjectRepository implements ProjectRepositoryInterface  {


//get user projects with all associated clients and statuses
public function getUserProjectswithClients()
    {

        return \User::with(array('projects', 'projects.clients', 'projects.statuses'))->find(Auth::user()->id); 

    }

} //end class

项目.php

<?php
use Illuminate\Database\Eloquent\ModelNotFoundException;

class Project extends Eloquent
{

    public function clients()
    {
        return $this->belongsTo('Client', 'client_id');
    }

    public function users()
    {
        return $this->belongsTo('User');
    }

    public function tasks() 
    {
        return $this->hasMany('Task');
    }


    public function status() // singular name, since it will be     single model
    {
        return $this->hasOne('Status');
        // equal to:
        // return $this->hasOne('Status', 'status_id');
    }



}

状态.php

<?php
use Illuminate\Database\Eloquent\ModelNotFoundException;

class Status extends Eloquent
{

    public function users()
    {
        return $this->belongsTo('User');
    }

// Status
public function project() // singular name, since it will be single model
{
    return $this->hasOne('Project');
    // equal to
    // return $this->hasOne('Project', 'status_id');
}

    public function tasks() 
    {
        return $this->hasMany('Task');
    }   

}

用户.php

<?php

use Zizaco\Confide\ConfideUser;
use Zizaco\Confide\ConfideUserInterface;

class User extends Eloquent implements ConfideUserInterface
{
    use ConfideUser;

    public function clients()
    {
        return $this->hasMany('Client');
    }

    public function projects()
    {
        return $this->hasMany('Project');
    }
    public function statuses()
    {
        return $this->hasMany('Status');
    }
    public function tasks()
    {
        return $this->hasMany('Task');
    }
        public function teams()
    {
        return $this->hasMany('Team');
    }


}

<?php

use Acme\Repositories\ProjectRepositoryInterface;

/**
 * UsersController Class
 *
 * Implements actions regarding user management
 */
class UsersController extends Controller
{

 public function profile() {


        //returning users projects
    $data["usersprojects"] = $usersprojects = $this->userrepo->getUserProjectswithClients();


  return $usersprojects;
}
}

【问题讨论】:

    标签: sql laravel eloquent relationship


    【解决方案1】:

    tldr; Eloquent 以这种方式为您的关系猜测外键:

    1. belongsTo 按方法​​名 (statuses() -> statuses_id)

    2。对于hasOne 使用调用模型getForeignKey() 方法($status-&gt;getForeignKey())

    这是错误的关系:

    // Project
    public function statuses() {
        return $this->hasOne('Status');
    }
    

    这是正确的,但仍然不好(复数名称):

    // Status
    public function projects()
    {
        return $this->hasOne('Project');
    }
    

    这是正确的关系,但缺少外键:

    public function statuses() {
        return $this->belongsTo('Status');
        // it is the same as:
        // return $this->belongsTo('Status', 'statuses_id');
    }
    

    因此,您的关系的正确和充分版本将是:

    // Project
    public function status() // singular name, since it will be single model
    {
        return $this->belongsTo('Status');
        // equal to:
        // return $this->belongsTo('Status', 'status_id');
    }
    
    // Status
    public function project() // singular name, since it will be single model
    {
        return $this->hasOne('Project');
        // equal to
        // return $this->hasOne('Project', 'status_id');
    }
    

    【讨论】:

    • 啊酷是的,现在对我来说更有意义了。我已经厌倦了您指定的关系模型,但这在 laravel 日志中引发了另一个错误:[2014-09-07 15:35:59] production.ERROR: exception 'BadMethodCallException' with message 'Call to undefined method Illuminate\Database\Query\Builder::statuses()' in /media/sf_Sites/tempus/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php:2117
    • 根据我写的,你不应该有statuses() 方法。接下来,错误是因为您没有执行查询并尝试获取相关状态。所以可能打电话给first(),然后是status。否则给我看代码,我会告诉你那里出了什么问题。
    • 已经用使用的代码编辑了我的问题,也许是我在 DbProjectRepository.php @JarekTkaczyk 中使用的查询
    • 是的,但你没有显示执行。我想它是这样的:Project::where('id', $id)-&gt;status(); 意味着您尝试在非模型对象(Euloquent Builder)上调用关系,所以您应该使用Project::where(..)-&gt;first()-&gt;status;
    • 我正在像这样执行它...return \User::with(array('projects', 'projects.clients', 'projects.statuses'))-&gt;find(Auth::user()-&gt;id);我向用户查询这个以获取身份验证用户项目,然后我从那里开始,我该如何重写它来实现这个因为我试图获取的不仅仅是项目的状态,我还想获取它所属的客户端,很快我就会想获取它的相关任务,我已经成功了
    猜你喜欢
    • 2013-10-03
    • 2017-07-19
    • 2017-10-24
    • 1970-01-01
    • 2017-11-03
    • 2021-09-25
    • 2015-01-21
    • 2017-01-14
    • 1970-01-01
    相关资源
    最近更新 更多