php - relations - uno a muchos en laravel
Laravel 4: forma elocuente de asociar una cláusula where a una relación cuando se construye una colección (2)
Como se indica en la pregunta, hay una forma de filtrar las direcciones primero y luego usar la carga ansiosa para cargar el objeto relacionado de los usuarios. Como tal:
$addressFilter = Addresses::with(''Users'')->where(''town'', $keyword)->first(); $users= $addressFilter->users;
por supuesto vincular con belongsTo en el modelo.
/// * Y en caso de que cualquier persona que lea desee también usar datos de usuarios prefiltrados, puede pasar un cierre al ''con''
$usersFilter = Addresses::with(array(''Users'' => function($query) use ($keyword){
$query->where(''somefield'', $keyword);
}))->where(''town'', $keyword)->first();
$myUsers = $usersFilter->users;
Esto puede ser una tontería, pero he estado buscando durante algún tiempo una respuesta adecuada a esto y todavía no he encontrado uno.
Entonces, esencialmente, todo lo que quiero hacer es unir dos tablas y adjuntar una condición where a toda la colección en función de un campo de la tabla unida.
Entonces digamos que tengo dos tablas:
users:
-id
-name
-email
-password
-etc
user_addresses:
-address_line1
-address_line2
-town
-city
-etc
En aras de la argumentación (darse cuenta de que este puede no ser el mejor ejemplo), supongamos que un usuario puede tener múltiples entradas de dirección. Ahora, laravel / eloquent nos brinda una forma agradable de completar las condiciones de una colección en forma de ámbitos, por lo que utilizaremos una de ellas para definir el filtro.
Entonces, si quiero obtener todos los usuarios con una dirección en smallville, puedo crear un alcance y relaciones de la siguiente manera:
Users.php (modelo)
class users extends Eloquent{
public function addresses(){
return $this->belongsToMany(''Address'');
}
public function scopeSmallvilleResidents($query){
return $query->join(''user_addresses'', function($join) {
$join->on(''user.id'', ''='', ''user_addresses.user_id'');
})->where(''user_addresses.town'', ''='', ''Smallville'');
}
}
Esto funciona, pero es un poco feo y estropea mis objetos elocuentes, ya que ya no tengo un buen atributo dinámico que contenga las direcciones de los usuarios, todo está repleto en el objeto del usuario.
He intentado varias otras cosas para hacer que esto funcione, por ejemplo, usar un cierre en la relación parecía prometedor:
// esto solo filtra en el momento de adjuntar la relación, por lo que se mostrarán todos los usuarios, pero solo se insertará la dirección donde coincida
User::with(array(''Addresses'' => function($query){
$query->where(''town'', ''='', ''Smallville'');
}));
// Esto no funciona para nada
User::with(''Addresses'')->where(''user_addresses.town'', ''='', ''Smallville'');
Entonces, ¿existe una forma ''Elocuente'' de aplicar cláusulas a las relaciones de una manera que filtre la colección principal y mantenga intactos mis objetos elocuentes? ¿O me han gustado tantos otros mimados por la elegante sintaxis de Eloquent hasta el punto en que estoy pidiendo demasiado?
Nota: soy consciente de que generalmente puedes evitar esto definiendo relaciones en la otra dirección (por ejemplo, accediendo primero a la tabla de direcciones), pero esto no siempre es ideal y no es lo que estoy pidiendo.
Gracias de antemano por cualquier ayuda.
En este punto, no hay medios por los cuales pueda filtrar el modelo primario en función de una restricción en los modelos relacionados. Esto significa que no puede obtener solo Users
que tengan user_address.town = ''Smallwille''
de un golpe.
Personalmente espero que esto se implemente pronto porque puedo ver a mucha gente pidiéndolo (incluyéndome a mí aquí).
La solución actual es desordenada, pero funciona:
$products = array();
$categories = Category::where(''type'', ''fruit'')->get();
foreach($categories as $category)
{
$products = array_merge($products, $category->products);
}
return $products;