【问题标题】:Eloquent Model with nested model issue具有嵌套模型问题的雄辩模型
【发布时间】:2020-05-08 10:48:47
【问题描述】:

我有几个看起来像这样的表:

1) 文章

  • 身份证
  • 姓名

2) article_options

  • 身份证
  • article_id
  • option_id

3) 选项

  • id

  • 姓名

一篇文章可以没有、一个或多个选项,我想在 RestAPI 中返回一个如下所示的 JSON 结构:

[{
  "id": 1,
  "name": "Article1",
  "options": [10]
},
{
  "id": 2,
  "name": "Article2",
  "options": [3, 10]
},
{
  "id": 3,
  "name": "Article3",
  "options": []
}]

其中 3 和 10 将是选项 ID。

我尝试了一些解决方案,但都没有奏效。这是我目前拥有的:

文章型号:

class Article extends Model
{
#    protected $with = ['Article_Option'];

    public function options()
    {
        return $this->hasMany('App\Article_Option');
    }
}

文章管理员:

class ArticleController extends Controller
{
    public function index()
    {
        $articles = Article::all();

        return response()->json(
            $articles
        , 200);
    }
}

我只是不明白应该如何配置模型和控制器来实现这一点。

请帮忙。

谢谢 哥比

[更新]

感谢隐藏的帮助。通过一些修改,我让它按照我想要的方式工作。这是所有代码...

文章型号:

namespace App;
use Illuminate\Database\Eloquent\Model;

class Article extends Model
{
  public function options()
  {
    return $this->belongsToMany('App\Option');
  }
}

文章控制器:

namespace App\Http\Controllers;
use App\Article;
use App\Http\Resources\Article as ArticleResource;
use Illuminate\Http\Request;

class ArticleController extends Controller
{
  public function index()
  {
    $articles = ArticleResource::collection(Article::all());

    return response()->json ($articles, 200);
  }
}

和资源:

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class Article extends JsonResource
{
  public function toArray($request)
  {
    return [
    'id' => $this->id,
    'name' => $this->name,
    'options' => $this->options->pluck('id')->all()
    ];
  }
}

【问题讨论】:

    标签: eloquent laravel-7


    【解决方案1】:

    article_options 是你的数据透视表,文章和选项之间的关系是多对多关系,laravel 为here 提供了一个函数。因此,您所要做的就是将关系添加到您的 article 模型中。

    public function options() {
        return $this->belongsToMany(Option::class);
    }
    

    那么在获取文章时,您可以调用该关系。

    $articles = Article::with('options')->get();
    

    这将抓取具有所有选项关系的所有文章,并以您想要的方式对其进行格式化。 Laravel 可以自动计算出它需要使用哪些字段来形成表之间的关系,所以不用担心,尽管它确实可以在 belongsToMany 函数中提供它们。

    如果您只想要 id,您可以将特定列传递给 with 函数,如下所示。

    $articles = Articles::with('options:id')->get()
    

    然后以 json 格式返回,您可以使用resources。资源有助于更好地格式化可用于实现您想要的模型的集合。您将需要为文章创建资源。在文章资源中,您可以根据需要对其进行格式化,并格式化选项,您可以使用集合方法通过从集合中提取字段将其转换为 id 数组。

    文章资源

    public function toArray($request)
    {
        return [
           'id' => $this->id,
           'name' => $this->name,
           'options' => $this->options->pluck('id')->all(),
        ];
    }
    

    所以一旦你得到了文章,你可以像这样退回它们

    return new ArticlesResource::collection($articles);
    

    如果稍后您希望为选项传递其他列,您可以创建一个选项资源并将其传递给您文章资源中的选项键。

    'options' => new OptionsResource::collection($this->options)
    

    【讨论】:

    • 到目前为止,我只更改了第一部分的代码(没有 toArray),但我得到了一个“找不到类 'Option::class'”。然而,它被定义为“类选项扩展模型”......
    • 您是否在终端中运行过composer dump-autoload?你在哪里使用Article_Option::class
    • 是一个错字 - 我应该只引用选项类。我已经在我的评论中纠正了这一点,并通过将“Option::class”替换为“App\Option”来让他的第一部分也能正常工作。为什么 ::class 不起作用?
    • Option::class 假定您调用它的位置与Option 模型在同一个命名空间中。所以你的文章模型在App\Article
    • 是的,所有模型都在App中
    猜你喜欢
    • 1970-01-01
    • 2021-08-11
    • 2013-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-27
    • 1970-01-01
    • 2014-12-05
    相关资源
    最近更新 更多