Laravel 5.6 API资源收集-未获取条件关系

时间:2018-09-04 14:42:45

标签: php laravel laravel-5

我正在经历我的第一个Laravel项目,并且实现了一个资源收集API,在其中我通过护照获取数据。除了关系外,似乎可以从模型中正确检索数据。情况如下:

item.php(模型)

class MySerializer(ModelSerializer):
    user_id = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(), source='user', write_only=True)
    class Meta:
        model = Model1
        fields = '__all__'

item.php(资源)

<?php

// Definizione Namespace
namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

/**
 * Classe Item
 */
class Item extends Model
{
    use SoftDeletes;

    // Dichiarazione Proprietà
    protected $table = 'item';
    protected $dateformat = 'Y-m-d';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'data_acquisto',
        'labeled',
        'estensione_garanzia',
        'stato',
        'data_dismissione',
        'note'
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'codice',
        'serial',
        'componente_id',
        'tipologia_id',
        'condizione_id',
        'locazione_id',
        'fornitore_id',
        'parent_id'
    ];

    /**
     * The attributes that should be mutated to dates.
     *
     * @var array
     */
    protected $dates = [
        'data_acquisto',
        'data_dismissione',
        'deleted_at'
    ];

    /**
     * All of the relationships to be touched.
     *
     * @var array
     */
    protected $touches = [
        'componenti',
        'condizioni',
        'fornitori',
        'locazioni',
        'tipologie'
    ];

    /**
     * Scope query item figli
     * Getter
     * @param array $query Query
     * @return array Query
     */
    public function scopeFigli($query)
    {
        return $query->where('parent_id', '!=', null);
    }

    /**
     * Componenti Correlati
     * Getter
     * @return object Componenti
     */
    public function componenti()
    {
        // Definizione relazione
        return $this->belongsTo('App\Componente');
    }

    /**
     * Condizioni Correlate
     * Getter
     * @return object Condizioni
     */
    public function condizioni()
    {
        // Definizione relazione
        return $this->belongsTo('App\Condizione');
    }

    /**
     * Fornitori Correlati
     * Getter
     * @return object Fornitori
     */
    public function fornitori()
    {
        // Definizione relazione
        return $this->belongsTo('App\Fornitore');
    }

    /**
     * Locazioni Correlate
     * Getter
     * @return object Locazioni
     */
    public function locazioni()
    {
        // Definizione relazione
        return $this->belongsTo('App\Locazione');
    }

    /**
     * Tipologie Correlate
     * Getter
     * @return object Tipologie
     */
    public function tipologie()
    {
        // Definizione relazione
        return $this->belongsTo('App\Tipologia');
    }
}

这是有关获取的数据示例的屏幕:

enter image description here

如上所示,没有任何关系。通过像这样建议地搜索和更改代码:

<?php

// Definizione Namespace
namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;
use App\Http\Resources\Componente as ComponenteResource;
use App\Http\Resources\Condizione as CondizioneResource;
use App\Http\Resources\Fornitore as FornitoreResource;
use App\Http\Resources\Locazione as LocazioneResource;
use App\Http\Resources\Tipologia as TipologiaResource;

class Item extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        parent::toArray($request);

        return [
            'id' => $this->id,
            'codice' => $this->codice,
            'data_acquisto' => $this->data_acqisto,
            'serial' => $this->serial,
            'labeled' => $this->labeled,
            'estensione_garanzia' => $this->estensione_garanzia,
            'stato' => $this->stato,
            'data_dismissione' => $this->data_dismissione,
            'note' => $this->note,
            'parent_id' => $this->parent_id,
            // Includi associazioni se caricate
            'componenti' => ComponenteResource::collection($this->whenLoaded('componenti')),
            'condizioni' => CondizioneResource::collection($this->whenLoaded('condizioni')),
            'fornitori' => FornitoreResource::collection($this->whenLoaded('fornitori')),
            'locazioni' => LocazioneResource::collection($this->whenLoaded('locazioni')),
            'tipologie' => TipologiaResource::collection($this->whenLoaded('tipologie'))
        ];
    }
}

或通过在模型中显式外键:

// Resoruce - Straight including relations instead of lazy load
[...]
'componenti' => ComponenteResource::collection($this->componenti),
[...]

我仍然没有找回关系。 谁能给我一些帮助/提示来解决这个问题?

预先感谢您的帮助。

2 个答案:

答案 0 :(得分:3)

下面的代码仅在显式加载时才显示Tipologie,以避免N + 1查询问题。

'tipologie' => TipologiaResource::collection($this->whenLoaded('tipologia'))

要加载Tipologie for Resource以显示它,您需要将其显式加载为:

$itemResource = new ItemResource($item->load('tipologia', ... other relationships...);

有关更多信息,请参见Eager Loading

编辑

很抱歉,您不了解关系的类型,就像@ luca-cattide所说的那样,collectionTo不应使用collection,正确的用法是:

TipologiaResource::make($this->tipologia);

或者:

new TipologiaResource($this->topologia);

但是我建议您先使用“加载”方法加载信息,否则,您将在数据库中搜索“项目”,然后通过“ typologie”进行搜索,依此类推,直到加载所有关系。

还有另一种无需加载项目即可加载信息的方式,如下所示:

new ItemResource(App\Item::find(1)->with(['tipologie', ... other relationships ... ])->get());

详细了解N + 1个查询问题here

答案 1 :(得分:1)

感谢@vinicius,但按照@CamiloManrique的this post的建议进行了更多搜索,我注意到在这些关系中,我试图从belongs_to端获取数据(因此实际上来自Item,而不来自ComponenteTipologia等)。就像::collection一样根本无法工作,除非由hasMany关系方调用

因此,我将::collectionwhenLoaded结合使用是这样重构的:

    // Includi associazioni se caricate
    'componente' => ComponenteResource::make($this->componente),
    'condizione' => CondizioneResource::make($this->condizione),
    'fornitore' => FornitoreResource::make($this->fornitore),
    'locazione' => LocazioneResource::make($this->locazione),
    'tipologia' => TipologiaResource::make($this->tipologia)

通过这种方式,可以正确提取数据。

再次感谢您的提示。