Laravel 7.x - связать модель с последним результатом в отношении принадлежит ко многим - PullRequest
0 голосов
/ 11 июля 2020

Если я ошибаюсь или у вас есть лучшее решение этой проблемы, я все слышу; -)

Программное обеспечение, над которым я работаю, позволяет пользователю добавлять документы в заказ, по умолчанию статус документа «видимый». Если пользователь решает удалить файл, добавляется второй статус «удален», поэтому пользователь может восстановить его в течение 14 дней; после этого добавляется другой статус («удален»).

документы и их соответствующие статусы работают нормально, я получаю несколько статусов - по запросу - начиная с самого нового. Поэтому я подумал, что было бы удобно автоматически объединять только те документы с соответствующим статусом, поскольку есть только один, но, к сожалению, Laravel не так убедителен, как я. Вот мой код:

class Order extends Model 
{
    public function documents()
    {
        return $this->hasMany('App\OrderDocument')
                    ->with('status')
                    ->whereHas('status', function($query) {
                        $query->first()->where('document_status_name', 'visible');
                    });
    }
}
class OrderDocument extends Model
{
    public function order()
    {
        return $this->belongsTo('App\Order');
    }

    public function status()
    {
        return $this->belongsToMany('App\DocumentStatus', 'order_documents_status', 'order_documents_id', 'status_id')
                    ->withPivot('created_at', 'updated_at', 'user_id')
                    ->withTimestamps()
                    ->orderBy('updated_at', 'desc');
    }
}
class DocumentStatus extends Model
{
    public function orderDocument()
    {
        return $this->belongsToMany('App\OrderDocument', 'order_documents_status', 'status_id', 'order_documents_id')
                    ->withPivot('user_id', 'created_at', 'updated_at')
                    ->orderBy('updated_at', 'desc');
    }
}

Если я изменю Модель заказа, используя это отношение

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

, все работает гладко, я получаю свой заказ с его документами и каждым документ может иметь много статусов, упорядоченных по created_at des c, но как только я добавляю условие whereHas, я получаю следующую ошибку:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'order_documents.id' in 'where clause' (SQL: select * from document_status inner join order_documents_status on document_status.document_status_id = order_documents_status.status_id where order_documents.id = order_documents_status.order_documents_id limit 1)

Конечно, order_documents.id может не найден, таблица не соединена, но я даже не могу понять, почему эта таблица загружена именно туда?

Есть ли у кого-нибудь советы, как запрашивать только последний элемент отношение "многие ко многим"? Я подумал об использовании globalScope для OrderDocument, потому что было бы проще «отключить» ограничение, если я действительно хочу, чтобы все документы игнорировали их статус, но я тоже не мог заставить это работать, что интересно с той же ошибкой SQL .

protected static function booted()
{
    static::addGlobalScope('visible', function (\Illuminate\Database\Eloquent\Builder $builder) {
        $builder->whereHas('status', function($query) {
            $query->first()->where('document_status_name', 'visible');
        });
    });
}

заранее большое спасибо!

1 Ответ

0 голосов
/ 15 июля 2020

Я нашел обходной путь для своих целей, но мне все равно был бы действительно интересен ответ на мой вопрос, потому что для моего понимания, почему не должно быть возможности связать модели с использованием условия ...

В качестве обходного пути я использую отношение Order -> OrderDocument не напрямую, а через средство доступа, в котором я возвращаю только те документы с соответствующим статусом.

public function getDocumentsDetailAttribute()
{
    $documents = [];
    $this->documents->each(function($document) use (&$documents) {
        if(!in_array($document->status->first()->document_status_name, ['visible'])) {
            return;
        }

        $documents[] = [
            'id' => $document->id,
            'name' => $document->name,
            'link' => route('orderdocument.download', ['orderDocument' => $document->id]),
            'created_at' => $document->created_at,
            'status' => $document->status->first()->document_status_name,
       ];
    });

    return $documents;
}

Спасибо!

...