Tengo un modelo Eloquent que tiene un modelo relacionado:
public function option() {
return $this->hasOne('RepairOption', 'repair_item_id');
}
public function setOptionArrayAttribute($values)
{
$this->option->update($values);
}
Cuando creo el modelo, no necesariamente tiene un modelo relacionado. Cuando lo actualizo, podría agregar una opción, o no.
Por lo tanto, debo verificar si existe el modelo relacionado, para actualizarlo o crearlo, respectivamente:
$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());
}
};
¿Dónde <related_model_exists>
está el código que estoy buscando?
Respuestas:
En php 7.2+ no se puede usar
count
en el objeto de relación, por lo que no hay un método único para todas las relaciones. Utilice el método de consulta en su lugar como @tremby proporcionado a continuación:solución genérica que funciona en todos los tipos de relación ( pre php 7.2 ):
Esto funcionará para cada relación ya que las propiedades dinámicas regresan
Model
oCollection
. Ambos implementanArrayAccess
.Entonces va así:
relaciones individuales:
hasOne
/belongsTo
/morphTo
/morphOne
relaciones de muchos:
hasMany
/belongsToMany
/morphMany
/morphToMany
/morphedByMany
fuente
count($relation)
Es una solución general para todas las relaciones. Funcionará paraModel
yCollection
, aunqueModel
no tiene ningún->count()
método.Collection
tiene su propio métodoisEmpty
, pero laempty
función genérica devuelve falso para un objeto (por lo tanto, no funcionará para una colección vacía).count($model->relation)
no funcionómorphTo
cuando la relación aún no tenía una asociación establecida. La identificación y el tipo externos son nulos y la consulta de db creada por Laravel es falsa y genera una excepción. Solía$model->relation()->getOtherKey()
como una solución alternativa.count(): Parameter must be an array or an object that implements Countable
Un objeto de relación pasa llamadas de métodos desconocidos a un generador de consultas elocuente , que está configurado para seleccionar solo los objetos relacionados. Ese generador a su vez pasa llamadas de métodos desconocidos a su generador de consultas subyacente .
Esto significa que puede usar los métodos
exists()
ocount()
directamente desde un objeto de relación:Tenga en cuenta los paréntesis después de
relation
:->relation()
es una llamada a la función (obtener el objeto de relación), en lugar de->relation
que Laravel configure un captador de propiedades mágicas para usted (obtener el objeto / objetos relacionados).Usar el
count
método en el objeto de relación (es decir, usar los paréntesis) será mucho más rápido que hacerlo$model->relation->count()
ocount($model->relation)
(a menos que la relación ya se haya cargado con entusiasmo) ya que ejecuta una consulta de conteo en lugar de extraer todos los datos de cualquier objeto relacionado de la base de datos, solo para contarlos. Del mismo modo, el usoexists
tampoco necesita extraer datos del modelo.Tanto
exists()
ycount()
el trabajo en todos los tipos de relación que he probado, así que al menosbelongsTo
,hasOne
,hasMany
, ybelongsToMany
.fuente
Prefiero usar el
exists
método:RepairItem::find($id)->option()->exists()
para verificar si el modelo relacionado existe o no. Está funcionando bien en Laravel 5.2
fuente
Después de Php 7.1 , la respuesta aceptada no funcionará para todo tipo de relaciones.
Porque dependiendo del tipo de relación, Eloquent devolverá a
Collection
, aModel
oNull
. Y en Php 7.1count(null)
lanzará unerror
.Entonces, para verificar si existe la relación, puede usar:
Para relaciones individuales: por ejemplo
hasOne
ybelongsTo
Para relaciones múltiples: Por ejemplo:
hasMany
ybelongsToMany
fuente
No estoy seguro de si esto ha cambiado en Laravel 5, pero la respuesta aceptada usando
count($data->$relation)
no funcionó para mí, ya que el solo hecho de acceder a la propiedad de relación causó que se cargara.Al final, un sencillo me
isset($data->$relation)
sirvió.fuente
$data->relation
sin$
(no se puede editar, debido al límite de 6 caracteres)$relation
, sería el nombre de su relación, tal$data->posts
o cual. Lo siento si eso fue confuso, quería dejar en claro querelation
no era una propiedad modelo concreta: PSe puede utilizar el relationLoaded método en el objeto del modelo. Esto salvó mi tocino, así que espero que ayude a alguien más. Me dieron esta sugerencia cuando hice la misma pregunta sobre Laracasts.
fuente
Como Hemerson Varela ya dijo en Php 7.1
count(null)
arrojará unerror
yhasOne
regresanull
si no existe una fila. Ya que tienes unhasOne
relación, usaría elempty
método para verificar:Pero esto es superfluo. No es necesario verificar si la relación existe, para determinar si debe hacer una
update
o unacreate
llamada. Simplemente use el método updateOrCreate . Esto es equivalente a lo anterior:fuente
Tuve que refactorizar completamente mi código cuando actualicé mi versión de PHP a 7.2+ debido al mal uso de la función de conteo ($ x). Esto es un verdadero dolor y también es extremadamente aterrador, ya que hay cientos de usos, en diferentes escenarios y no hay reglas para todos.
Reglas que seguí para refactorizar todo, ejemplos:
$ x = Auth :: user () -> posts-> find (6); (verifique si el usuario tiene un id de publicación = 6 usando -> find ())
$ x = Auth :: usuario () -> perfil-> departamentos; (verifique si el perfil tiene algunos departamentos, puede haber muchos departamentos)
$ x = Auth :: user () -> perfil-> get (); (verifique si el usuario tiene un perfil después de usar un -> get ())
Espero que esto pueda ayudar, incluso 5 años después de que se haya hecho la pregunta, ¡esta publicación de stackoverflow me ha ayudado mucho!
fuente