with relations relacion muchos hasone ejemplo belongsto php orm laravel laravel-4 eloquent

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;