我在尝试从控制器返回 hasOne 到前端时遇到错误。

huangapple go评论59阅读模式
英文:

I am getting an error when trying to access and return hasOne from the controller to the frontend

问题

> Response::setContent(): 参数 #1 ($content) 必须是可选的字符串类型

在尝试从控制器返回 hasOne 到前端时,我遇到了上述错误。
我创建了两个模型,Product 和 Images。

Product 模型

<?php

namespace App\Models;

use Exception;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    use HasFactory;
    protected $fillable = [
        'sku',
        'name',
        'price',
        'status',
        'imageId'
    ];

    public function images(){
        return $this->hasOne(Image::class, 'id', 'imageId');
    }
}

Image 模型

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Image extends Model
{
    use HasFactory;
    protected $fillable = [
        'imageName',
        'imageLink'
    ];
}

Product 控制器

<?php

namespace domain\Services;

use App\Models\Product;
use App\Models\Image;
use Exception;
use PhpParser\Node\Stmt\TryCatch;

class ProductService
{
    protected $item;
    public function __construct()
    {
        $this->item = new Product();
    }
    public function all()
    {
            return $this->item->images();
    }

当我尝试在控制器的 all() 函数中返回模型中的 images() 函数时,我遇到了这个错误。

英文:

> Response::setContent(): Argument #1 ($content) must be of type ?string

I am getting the above error, when trying to access and return hasOne from the controller to the front end.
I have created two models Product and Images.

Product Model

&lt;?php

namespace App\Models;

use Exception;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    use HasFactory;
    protected $fillable = [
        &#39;sku&#39;,
        &#39;name&#39;,
        &#39;price&#39;,
        &#39;status&#39;,
        &#39;imageId&#39;
    ];

    public function images(){
        return $this-&gt;hasOne(Image::class,&#39;id&#39;,&#39;imageId&#39;);
    }
}

Image Model

&lt;?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Image extends Model
{
    use HasFactory;
    protected $fillable = [
        &#39;imageName&#39;,
        &#39;imageLink&#39;
    ];
}

Product Controller

&lt;?php

namespace domain\Services;

use App\Models\Product;
use App\Models\Image;
use Exception;
use PhpParser\Node\Stmt\TryCatch;

class ProductService
{
    protected $item;
    public function __construct()
    {
        $this-&gt;item = new Product();
    }
    public function all()
    {
            return $this-&gt;item-&gt;images();
    }

I am getting the error when trying to return the function images function in the Model using the all() function in the controller.

答案1

得分: 0

首先,您拥有的是一种belongsTo关系,因为产品模型具有一个ImageId列。https://laravel.com/docs/10.x/eloquent-relationships#one-to-one

您的控制器方法"all"的目的是什么?
您是否想显示所有产品及其图像?如果是的话,您应该这样做:

return Product::query()
    ->with('images')
    ->get();

https://laravel.com/docs/10.x/eloquent-relationships#eager-loading

并且您可以在已填充的模型上调用关系,类似于:

Product::first()->images

要注意Product::first()->images和Product::first()->images()之间的区别。

只是一个快速的提示。如果它是一对一关系,那么您的关系方法应该命名为image(),而不是images()。

英文:

First of all, what you have is a belongsTo relation since the product model has an ImageId column. https://laravel.com/docs/10.x/eloquent-relationships#one-to-one

What is the purpose of your controller method "all"?
Do you want to show all of your products with their image? If so then you should do something like this:

return Product::query()
-&gt;with(&#39;images&#39;)
-&gt;get();

https://laravel.com/docs/10.x/eloquent-relationships#eager-loading

And you can call relations on a hydrated model. Something like:

Product::first()-&gt;images

Be aware of the difference between Porduct::first()->images and Product::first()->images().

Just a quick note. If it is a one-to-one relation then your relation method should be named image() instead of images().

答案2

得分: 0

以下是翻译好的内容:

总的来说,当你充分利用Laravel的优势时,它表现最佳。例如,在你上面的代码中,你使用了$imageId而不是$image_id,然后你被迫在Product模型的关系中包含id以进行搜索,而不是使用Laravel期望的$image_id在product表中。然后在模型中只需使用:

public function Image()
{
    return $this->hasOne(Image::class);
}

请注意函数名称与模型名称相同。由于你在product表中使用了$image_id,因此不需要进一步操作。

另外考虑将产品控制器命名为ProductController,而不是ProductService。

回答你的问题:
在产品控制器的构造函数中,你初始化了一个新的Product模型,没有任何与数据库的引用,这是一个空模型,然后你在all函数中调用它,并请求images属性,但在你显示的代码中没有任何可以从数据库获取产品模型的内容。

而是考虑像下面这样的函数,例如:

public function show(Product $product)
{
    // 然后调用$product变量上的image属性,Laravel将为你获取它
    $product->load('Image');
    return response()->json($product);
}

在你的路由中添加 'show_product/{product}' 并使用所需的产品id 调用它。

英文:

In general Laravel works best when you take advantage of its strengths.
For example in your code above you have $imageId instead of $image_id and you are then forced to include the id to search for in your relationship on the Product model instead use what Laravel is expecting ie $image_id in the product table. Then in the model just use

Public function Image()
{
    return $this-&gt;hasOne(Image::class);
}

Note the function name is the same as the model name. And since you have used $image_id in the product table nothing further is required.

Also consider calling the product controller ProductController and not ProductService

In answer to your question:
In the constructor of the product controller you initialise a new Product model without any reference to the database this is an empty model you then call this in the all function and ask for the images property but there is nothing in the code you have displayed which will get a product model from the database.

Instead consider something like the function below for example

Public function show(Product $product)
{
 // then call the image property on the      $product variable which Laravel will get for you 
$product-&gt;load(‘Image’);
return response()-&gt;json($product);
}

In your route add ‘show_product/{product}’ and call it with the id of the product you want.

答案3

得分: 0

这是我的解决方案

public function all()
{
    $products = $this->item->with(['images' => function($query) {
        return $query->select(['id', 'imageName', 'imageLink']);
    }])->get();

    return $products;
}
英文:

This is my solution

public function all()
    {
        $products = $this-&gt;item-&gt;with([&#39;images&#39; =&gt; function($query) {
            return $query-&gt;select([&#39;id&#39;, &#39;imageName&#39;,&#39;imageLink&#39;]);
        }])-&gt;get();
        
        return $products;
    }

</details>



huangapple
  • 本文由 发表于 2023年5月29日 18:25:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76356526.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定