2011-06-28 10 views
5

हाय वहाँ सिर्फ सवालसबसे अच्छा तरीका है Yii में मॉडल से संबंधित डेटा प्राप्त और वापसी json

im एक परियोजना है कि सामने के छोर पर sproutcore उपयोग कर रहा है के लिए एक शोकहारा आवेदन पर काम करने के लिए।

मेरा प्रश्न वास्तव में जेसन लौटने की आवश्यकता होने पर अन्य संबंधित मॉडल के साथ मॉडल से डेटा को पकड़ने का सबसे प्रभावी तरीका क्या है। मैंने कल पढ़ा था कि मेरे उदाहरण के लिए एरे के साथ काम करते समय डीएओ परत को काम करने की सिफारिश की गई है, यह मेरे पास अब तक है।

मेरे पास ग्राहकों की एक सूची है, प्रत्येक ग्राहक 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']; 
      } 

    } 

इस लौटा रहा है मैं अब तक चाहते हैं, लेकिन यह क्या im के बाद प्राप्त करने के लिए सबसे प्रभावी तरीका है ??

+0

यदि आपके पास अपनी तालिका 'क्लाइंट' के लिए CACTiveRecord ऑब्जेक्ट नहीं है, तो कृपया इसे पहले करें (देखें: http://www.yiiframework.com/doc/guide/1।1/en/database.ar)। और इसके बाद आप डेटा को सरल प्राप्त कर पाएंगे: '$ क्लाइंट = क्लाइंट :: मॉडल() -> के साथ ('ब्रांड') -> findByAttributes (सरणी ('स्थिति' => 1));' –

+0

जैसा कि मैं जेसन लौटने जा रहा हूं, डीएओ परत के साथ काम करना बेहतर नहीं है क्योंकि आरआर का उपयोग करके क्यूरी प्रदर्शन करने के लिए मुझे बहुत अधिक जानकारी मिलती है। तो जब मैं सरणी को एन्कोड करने के लिए आती हूं तो मुझे वापस लौटने की आवश्यकता से अधिक वस्तुओं के साथ समाप्त होता है ?? –

+0

यदि मैं सही से समझ गया: 1) आप कॉलम लिख सकते हैं जिसे आप चुनना चाहते हैं (मॉडल क्लास 'क्लाइंट 'फेंकें और' ब्रांड' से संबंध बनाएं) 2) इसके बाद, इन 2.1 का चयन करने के बाद' foreach' कथन करें) और जेसन में कनवर्ट करें जैसा कि आपने अपने प्रश्न उदाहरण / में किया है, फिर भी मैं टेबल के लिए मॉडल बनाने के लिए पहले की सिफारिश करता हूं। मैं इसे पहले करता हूं और यदि मेरे पास टेबल पर कुछ वैश्विक परिवर्तन हुए हैं, तो मैं केवल अपनी मॉडल कक्षा बदलता हूं। –

उत्तर

1

यदि आप with() कार्यक्षमता का उपयोग कर CActiveRecord का उपयोग नहीं करना चाहते हैं, तो आपको brand तालिका में शामिल एक SQL क्वेरी लिखनी चाहिए।

$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 में भी शामिल हो सकते हैं और प्रत्येक ब्रांड के लिए सभी संबंधित परियोजनाओं को पुनर्प्राप्त कर सकते हैं।

+0

अरे फिर से galymzhan, मेरे सभी yii संबंधित विषयों का जवाब दे रहा है !! यह एक और अधिक समझदार दृष्टिकोण प्रतीत होता है, हालांकि आपके उदाहरण की कोशिश करने पर मैं जेसन को अच्छी तरह से लौटने के लिए संघर्ष कर रहा था, एफपी जेएसन में सरणी को परिवर्तित करते समय कुछ फंकी चीजें करता है। मैं ग्राहक अनुरोध के लिए आवश्यक सरणी बनाने के लिए आपके उदाहरण के साथ प्रयास करना जारी रखता हूं! –

3

सेटअप ग्राहक मॉडल

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 "*" 
    } 

} 

सेटअप ब्रांड मॉडल

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 "*" 
    } 

} 

अपनी कार्रवाई समारोह

$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 
     ) 
    ) 
    ... 
) 

*/ 

में ग्राहक/ब्रांड खोज करें यह आप चाहते थे है? मुझे एहसास है, अगर आप केवल ब्रांड आईडी (किसी और डेटा पर नहीं) चुनना चाहते हैं तो आप एसक्यूएल और GROUP_CONCAT (MySQL) द्वारा खोज सकते हैं और कॉमा से अलग एक पंक्ति में क्लाइंट के लिए सभी ब्रांड आईडी चुन सकते हैं। 1,2,3,4,5,20,45,102

1

मुझे एहसास है कि यह पुराना है, लेकिन मैं खुद को एक समाधान की तलाश में था और मैंने सोचा कि यह एक अच्छा था।

मेरी आधार नियंत्रक वर्ग (संरक्षित/अवयव/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; 
} 

अब, एक वस्तु, या ऑब्जेक्ट की श्रेणी पर renderJsonDeep बुला, वस्तु सांकेतिक शब्दों में बदलना होगा (रों) जेएसओएन में आपके द्वारा खींचे गए किसी भी रिश्ते सहित, उन्हें डीबीक्रिटिरिया में 'साथ' परम में जोड़कर।

यदि बच्चे के ऑब्जेक्ट के कोई रिश्ते हैं, तो वे जेएसओएन में भी सेट किए जाएंगे, क्योंकि GetAttributesDeep को रिकर्सिव कहा जाता है।

उम्मीद है कि यह किसी की मदद करेगा।