[英]Yii framework: Using data from related Active Record models for searching
[英]best way to get related data from models in yii and return json
你好只是問題
我正在為一個在前端使用sproutcore的項目開發一個寧靜的應用程序。
我的問題是,當需要返回 json 時,從 model 和其他相關模型中獲取數據的最有效方法是什么。 我昨天讀到它建議在使用 arrays 時使用 DAO 層,所以對於我的示例來說,這就是我目前所擁有的。
我有一份客戶名單,每個客戶都有 HAS_MANY 品牌,每個品牌都有 HAS_MANY 項目。 沒有得到一個很好的客戶群與他們的品牌繼承人我所擁有的
$clients = Yii::app()->db->createCommand('select client.* from client where client.status = 1')->queryAll();
foreach($clients as $ckey => $client)
{
$clients[$ckey] = $client;
$brand_ids = Yii::app()->db->createCommand('select brand.id as brand_id, brand.client_id as b_client_id from brand where brand.client_id ='.$client['id'])->queryAll();
foreach($brand_ids as $bkey => $brand_id)
{
$clients[$ckey]['brands'][] = $brand_id['brand_id'];
}
}
到目前為止,這正在返回我想要的東西,但這是實現我所追求的最有效的方法嗎?
安裝客戶端model
class Client extends CActiveRecord
{
//...
/**
* @return array relational rules.
*/
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'brands' => array(self::HAS_MANY, 'Brand', 'client_id'),
);
}
//...
public function defaultScope() {
return array('select'=>'my, columns, to, select, from, client'); //or just comment this to select all "*"
}
}
設置品牌model
class Brand extends CActiveRecord
{
//...
/**
* @return array relational rules.
*/
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'client' => array(self::BELONGS_TO, 'Client', 'client_id'),
);
}
//...
//...
public function defaultScope() {
return array('select'=>'my, columns, to, select, from, brand'); //or just comment this to select all "*"
}
}
在您的操作中進行客戶/品牌搜索 function
$clients = Client::model()->with('brands')->findAllByAttributes(array('status'=>1));
$clientsArr = array();
if($clients) {
foreach($clients as $client) {
$clientsArr[$client->id]['name'] = $client->name; //assign only some columns not entire $client object.
$clientsArr[$client->id]['brands'] = array();
if($client->brands) {
foreach($client->brands as $brand) {
$clientsArr[$client->id]['brands'][] = $brand->id;
}
}
}
}
print_r($clientsArr);
/*
Array (
[1] => Array (
name => Client_A,
brands => Array (
0 => Brand_A,
1 => Brand_B,
2 => Brand_C
)
)
...
)
*/
這是你想要的嗎? 我意識到,如果您只想要 select 品牌 ID(沒有其他數據),您可以通過 sql 和GROUP_CONCAT (MySQL)和 select 搜索所有品牌 ID 的客戶。 1,2,3,4,5,20,45,102
。
我意識到這已經過時了,但我自己也在尋找解決方案,我認為這是一個很好的解決方案。
在我的基礎 Controller class (protected/Components/Controller.php) 我添加了以下函數:
protected function renderJsonDeep($o) {
header('Content-type: application/json');
// if it's an array, call getAttributesDeep for each record
if (is_array($o)) {
$data = array();
foreach ($o as $record) {
array_push($data, $this->getAttributesDeep($record));
}
echo CJSON::encode($data);
} else {
// otherwise just do it on the passed-in object
echo CJSON::encode( $this->getAttributesDeep($o) );
}
// this just prevents any other Yii code from being output
foreach (Yii::app()->log->routes as $route) {
if($route instanceof CWebLogRoute) {
$route->enabled = false; // disable any weblogroutes
}
}
Yii::app()->end();
}
protected function getAttributesDeep($o) {
// get the attributes and relations
$data = $o->attributes;
$relations = $o->relations();
foreach (array_keys($relations) as $r) {
// for each relation, if it has the data and it isn't nul/
if ($o->hasRelated($r) && $o->getRelated($r) != null) {
// add this to the attributes structure, recursively calling
// this function to get any of the child's relations
$data[$r] = $this->getAttributesDeep($o->getRelated($r));
}
}
return $data;
}
現在,在 object 或對象數組上調用 renderJsonDeep 將對 JSON 中的對象進行編碼,包括您提取的任何關系,例如將它們添加到 DbCriteria 中的“with”參數。
如果子 object 有任何關系,則這些關系也將在 JSON 中設置,因為 getAttributesDeep 是遞歸調用的。
希望這可以幫助某人。
如果您不想通過with()
功能使用 CActiveRecord,那么您應該編寫一個 SQL 查詢加入brand
表。
$rows = Yii::app()->db
->createCommand(
'SELECT c.*, b.id as brand_id
FROM client c INNER JOIN brand b
WHERE c.status = 1 AND b.client_id = c.id')
->queryAll();
$clients = array();
foreach ($rows as row) {
if (!isset($clients[$row['id']])) {
$clients[$row['id']] = $row;
$clients[$row['id']]['brands'] = array();
}
$clients[$row['id']]['brands'][] = $row['brand_id'];
}
這比執行一次查詢來檢索所有客戶,然后執行 N 次查詢來獲取他們的品牌(其中 N 是客戶的數量)要高效得多。 您還可以加入您的第三個表projects
並檢索每個品牌的所有相關項目。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.