私は、関連するモデルを持つEloquentモデルを持っています:
public function option() {
return $this->hasOne('RepairOption', 'repair_item_id');
}
public function setOptionArrayAttribute($values)
{
$this->option->update($values);
}
モデルを作成するときに、必ずしも関連するモデルがあるわけではありません。更新するときに、オプションを追加するかどうかを選択します。
そのため、関連するモデルが存在するかどうかを確認し、それぞれ更新または作成する必要があります。
$model = RepairItem::find($id);
if (Input::has('option')) {
if (<related_model_exists>) {
$option = new RepairOption(Input::get('option'));
$option->repairItem()->associate($model);
$option->save();
$model->fill(Input::except('option');
} else {
$model->update(Input::all());
}
};
<related_model_exists>
は探しているコードです。
php 7.2 +では、リレーションオブジェクトでcount
を使用できないため、すべてのリレーションに万能メソッドはありません。以下に示す@trembyとして代わりにクエリメソッドを使用します。
$model->relation()->exists()
すべての関係タイプで機能する一般的なソリューション(php 7.2より前):
if (count($model->relation))
{
// exists
}
動的プロパティはModel
またはCollection
を返すため、これはすべてのリレーションに対して機能します。両方ともArrayAccess
を実装します。
したがって、次のようになります。
単一の関係:hasOne
/belongsTo
/morphTo
/morphOne
// no related model
$model->relation; // null
count($model->relation); // 0 evaluates to false
// there is one
$model->relation; // Eloquent Model
count($model->relation); // 1 evaluates to true
多対多の関係:hasMany
/belongsToMany
/morphMany
/morphToMany
/morphedByMany
// no related collection
$model->relation; // Collection with 0 items evaluates to true
count($model->relation); // 0 evaluates to false
// there are related models
$model->relation; // Collection with 1 or more items, evaluates to true as well
count($model->relation); // int > 0 that evaluates to true
リレーションオブジェクト は、未知のメソッド呼び出しを Eloquent query Builder に渡します。これは、関連オブジェクトのみを選択するように設定されています。そのBuilderは、未知のメソッド呼び出しをits基礎となる query Builder に渡します。
つまり、リレーションオブジェクトから exists()
または count()
メソッドを直接使用できます。
$model->relation()->exists(); // bool: true if there is at least one row
$model->relation()->count(); // int: number of related rows
relation
の後の括弧に注意してください:->relation()
は、Laravel(関連オブジェクトを取得する)によってマジックプロパティゲッターが設定する->relation
とは対照的に、関数呼び出し(リレーションオブジェクトを取得する)です。
リレーションオブジェクトでcount
メソッドを使用する(つまり、かっこを使用する)ことは、すべてのデータをプルするのではなく、カウントクエリを実行するため、$model->relation->count()
またはcount($model->relation)
を実行するよりもはるかに高速です(リレーションが既に読み込まれている場合を除く)データベースからの関連オブジェクト、それらを数えるためだけに。同様に、exists
を使用しても、モデルデータをプルする必要はありません。
exists()
とcount()
は両方とも、私が試したすべての関係タイプで機能するため、少なくともbelongsTo
、hasOne
、hasMany
、およびbelongsToMany
です。
exists
メソッドを使用したい:
RepairItem::find($id)->option()->exists()
関連モデルが存在するかどうかを確認します。 Laravel 5.2では正常に動作しています
Php 7.1の後、受け入れられた答えはすべてのタイプの関係に対して機能しません。
関係のタイプに応じて、EloquentはCollection
、Model
、またはNull
を返します。そしてPhp 7.1count(null)
ではerror
がスローされます。
したがって、リレーションが存在するかどうかを確認するには、次を使用できます。
単一の関係の場合:例えばhasOne
およびbelongsTo
if(!is_null($model->relation)) {
....
}
複数の関係の場合:例:hasMany
およびbelongsToMany
if ($model->relation->isNotEmpty()) {
....
}
Laravel 5でこれが変更されたかどうかはわかりませんが、count($data->$relation)
を使用した受け入れられた答えは、リレーションプロパティにアクセスするまさにその行為が原因でロードされるため、うまくいきませんでした。
最後に、簡単なisset($data->$relation)
が私のためにトリックをしました。
Hemerson VarelaがPhp 7.1で既に述べたように、count(null)
はerror
をスローし、行が存在しない場合はhasOne
がnull
を返します。 hasOne
relationがあるので、empty
メソッドを使用して以下を確認します。
$model = RepairItem::find($id);
if (!empty($temp = $request->input('option'))) {
$option = $model->option;
if(empty($option)){
$option = $model->option()->create();
}
$option->someAttribute = temp;
$option->save();
};
しかし、これは不要です。 update
またはcreate
の呼び出しを行う必要があるかどうかを判断するために、関係が存在するかどうかを確認する必要はありません。 pdateOrCreate メソッドを使用するだけです。これは上記と同等です。
$model = RepairItem::find($id);
if (!empty($temp = $request->input('option'))) {
$model->option()
->updateOrCreate(['repair_item_id' => $model->id],
['option' => $temp]);
}
モデルオブジェクトで relationLoaded メソッドを使用できます。これは私のベーコンを救ったので、うまくいけば他の人を助けます。 Laracastsで同じ質問をしたとき、私は この提案が与えられた でした。
リレーションが既に存在するかどうかを確認したいので、update
またはcreate
を実行できます。ただし、 pdateOrCreate メソッドのため、これは必要ありません。
これを行うだけです:
$model = RepairItem::find($id);
$model->option()
->updateOrCreate(['repair_item_id' => $model->id],['option' => 'A']);