#php #laravel
#php #laravel
Вопрос:
Я начинающий веб-разработчик. У меня небольшая проблема с моей моделью.
У меня есть эта миграция и модель:
Schema::create('stopwatches', function (Blueprint $table) {
$table->increments('id');
$table->integer('case_id')->unsigned();
$table->foreign('case_id')->references('id')->on('case_instances')->onDelete('cascade');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
Schema::create('timecycles', function (Blueprint $table) {
$table->increments('id');
$table->integer('timecycleable_id');
$table->string('timecycleable_type');
$table->integer('case_id')->unsigned();
$table->foreign('case_id')->references('id')->on('case_instances')->onDelete('cascade');
$table->boolean('status')->default(0);
$table->integer('worked_time')->default(0);
$table->timestamps();
});
class Stopwatch extends Model
{
protected $fillable = [
'case_id',
'user_id'
];
protected $casts = [
'id' => 'int',
'case_id' => 'int',
'user_id' => 'int',
];
protected $dates = [
'created_at',
'updated_at'
];
public function timeCycle()
{
return $this->morphMany(Timecycle::class, 'timecycleable');
}
public function caseInstance()
{
return $this->belongsTo(CaseInstance::class, 'case_id');
}
class Timecycle extends Model
{
protected $fillable = [
'case_id',
'timecycleable_id',
'timecycleable_type',
'status',
'worked_time'
];
protected $casts = [
'id' => 'int',
'case_id' => 'int',
];
protected $dates = [
'created_at',
'updated_at'
];
public function stopwatch()
{
return $this->morphTo();
}
}
Во временных циклах у меня есть 2 записи со статусом = 0 и статусом = 1: https://ibb.co/5vyh316
Мне нужны мои секундомеры только с одним временным циклом со статусом = 1.
Я создаю этот код:
return $this->stopwatch::with(['timeCycle', 'caseInstance'])
->where('user_id', Auth()->user()->id)
->where('updated_at', '<=', CarbonCarbon::now()->subSeconds(30)->toDateTimeString())
->whereHas('timeCycle', function ($q) {
$q->where('status', 1);
})
->get();
В результате у меня есть элементы стенда: https://ibb.co/WnJ58Kc
Что не так в моем коде?
Как я могу это исправить?
Пожалуйста, помогите мне.
Комментарии:
1. Просто чтобы помочь вам понять,
whereHas
это условие для секундомера, поэтому загружаются только секундомеры, имеющие требуемый временной цикл, затем вы просите его загрузить отношение, используяwith
(без ограничений), чтобы оно загружало все временные циклы отфильтрованных секундомеров
Ответ №1:
На самом деле вы довольно близки, но whereHas()
это не влияет на загруженные записи. Используйте то же предложение в своем with()
заявлении:
return $this->stopwatch::with(['timeCycle' => function ($q) {
$q->where('status', 1); // If you only want 1, you can do `->limit(1)` as well
}, 'caseInstance'])
->where('user_id', Auth()->user()->id)
->where('updated_at', '<=', CarbonCarbon::now()->subSeconds(30)->toDateTimeString())
->whereHas('timeCycle', function ($q) {
$q->where('status', 1);
})
->get();
Теперь, при циклическом просмотре ваших данных, каждый $record->timeCycle
из них будет включать только то, что указано в with()
предложении.
Ответ №2:
Вероятно, проблема вызвана with('timeCycle')
предложением. Если вы хотите ограничить свой запрос отношением, вам нужно указать его как в the whereHas
, так и в the with()
, в противном случае при активной загрузке будут извлечены все элементы, делающие whereHas
их неактуальными. Попробуйте это:
return $this
->stopwatch::with([
'caseInstance',
'timeCycle' => function ($query) {
$query->where('status', 1);
}
])
->where('user_id', Auth()->user()->id)
->where('updated_at', '<=', now()->subSeconds(30)->toDateTimeString())
->whereHas('timeCycle', function ($query) {
$query->where('status', 1);
})
->get();
Конечно, учитывая, что оба ограничения равны, вы можете сохранить его в переменной и передать его обоим методам:
$timeCycleContraint = function ($query) {
$query->where('status', 1);
};
return $this
->stopwatch::with([
'caseInstance',
'timeCycle' => $timeCycleContraint
])
->where('user_id', Auth()->user()->id)
->where('updated_at', '<=', now()->subSeconds(30)->toDateTimeString())
->whereHas('timeCycle', $timeCycleContraint)
->get();