问题
Is it possible to access more than one model deep in a relationship in Lithium?
For example, I have a User model:
class Users extends \lithium\data\Model {
public $validates = array();
public $belongsTo = array("City");
}
and I have a City model:
class Cities extends \lithium\data\Model {
public $validates = array();
public $belongsTo = array("State");
}
and a State model, and so on.
If I'm querying for a User, with something similar to Users::first()
, is it possible to get all the relationships included with the results? I know I can do Users::first(array('with' => 'City'))
but I'd like to have each City return its State model, too, so I can access it like this:
$user->city->state->field
Right now I can only get it to go one deep ($user->city
) and I'd have to requery again, which seems inefficient.
回答1:
I am guessing you are using SQL?
Lithium is mainly designed for noSQL db´s, so recursiveness / multi joins are not a design goal.
- You could set up a native sql join query and cast it on a model.
- query the city with Users and State as joins.
- you could setup a db based join view and li3 is using it as a seperate model.
- you probably should split your planned recursive call into more than one db requests.
Think about the quotient of n Cities to m States. => fetch the user with city and then the state by the state id. => pass that as two keys or embed the state info. This would be acceptable for Users::all() queries aswell.
Example using Lithiums util\Set Class:
use \lithium\util\Set;
$users = Users::all(..conditions..);
$state_ids = array_flip(array_flip(Set::extract($users->data(), '/city/state_id')));
$stateList = States::find('list',array(
'conditions' => array(
'id' => $state_ids
),
));
回答2:
Using a recent master you can use the following nested notation:
Users::all( array(
'with' => array(
'Cities.States'
)
));
It will do the JOINs for you.
回答3:
You can set up relationships in this way, but you have to use a more verbose relationship definition. Have a look at the data that gets passed when constructing a Relationship for details about the options you can use.
class Users extends \lithium\data\Model {
public $belongsTo = array(
"Cities" => array(
"to" => "app\models\Cities",
"key" => "city_id",
),
"States" => array(
"from" => "app\models\Cities",
"to" => "app\models\States",
"key" => array(
"state_id" => "id", // field in "from" model => field in "to" model
),
),
);
}
class Cities extends \lithium\data\Model {
public $belongsTo = array(
"States" => array(
"to" => "app\models\States",
"key" => "state_id",
),
);
}
class States extends \lithium\data\Model {
protected $_meta = array(
'key' => 'id', // notice that this matches the value
// in the key in the Users.States relationship
);
}
When using the States relationship on Users, be sure to always include the Cities relationship in the same query. For example:
Users::all( array(
'with' => array(
'Cities',
'States'
)
) );
I have never tried this using belongsTo relationships, but I have it working using hasMany relationships in the same way.
来源:https://stackoverflow.com/questions/9836392/accessing-more-than-one-model-deep-relationships-in-lithium