Hi,
Im using CArJSON Extension to encode Models with Relations to JSON.
Problem:
The CArJSON only respect attributes for relational that is BELONGS_TO, for HAS_MANY it returns all fields.
Usage:
Yii::import('application.extensions.json.CArJSON');
$users = Locals::model()->findAll();
$json = new CArJSON();
$relations = array('parties');
$attributes = array(
'root' => array('id', 'name'),
'parties' => array( 'id', 'name' ), // PROBLEM IS HERE, THE CARJSON DO NOT RESPECT AND RETURN ALL TABLE FIELDS WHEN ITS HAS_MANY RELATION.
);
echo $json->toJSON($users, $relations, $attributes);
Local.php Model:
public function relations() {
return array(
'parties'=>array(self::HAS_MANY, 'Party', 'local_id'),
);
}
JSON Response: (Problem: Is returning all ‘parties’ fields.)
[{"attributes":{"id":"15","name":"Local Test"},"relations":{"parties":[{"id":"12","local_id":"15","name":"Partie 1","info":null,"datetime":"2013-10-10 10:10:10"}]}}]
CArJSON.php:
/**
* JSON extension class.
*
*
* @package Extension
* @author Emanuele Ricci
* @copyright (c) 2010 Emanuele Ricci
* @license http://www.designfuture.it
*/
class CArJSON {
private $owner;
private $relations;
private $relations_allowed;
private $attributes;
private $jsonString;
/*
* array (
* 'root'=> array of attributes,
* 'relation_name' => array of attributes,
* )
*
* if a relation_name is not setted or defined we will take all attributes
*
*/
public function toJSON( $model, $relations, $attributesAllowed=array() ){
$this->owner = $model;
$this->relations_allowed = $relations;
$this->attributes = $attributesAllowed;
$this->jsonString = '';
if ( !is_array($this->owner) ) {
$this->owner = array();
$this->owner[] = $model;
}
return $this->getJSON();
}
private function getJSON() {
foreach ( $this->owner as $o ) {
$result = $this->getJSONModel( $o );
if ( !$result ) return false;
else $this->jsonString .= $result . ',';
}
$this->jsonString = substr($this->jsonString, 0, -1);
$this->jsonString = '['.$this->jsonString.']';
return $this->jsonString;
}
private function getJSONModel( $obj ) {
if (is_subclass_of($obj,'CActiveRecord')){
$attributes = $obj->getAttributes( $this->attributes['root'] );
$this->relations = $this->getRelated( $obj );
$jsonDataSource = array('attributes'=>$attributes,'relations'=>$this->relations);
return CJSON::encode($jsonDataSource);
}
return false;
}
private function getRelated( $m )
{
$related = array();
$obj = null;
$md=$m->getMetaData();
foreach($md->relations as $name=>$relation){
if ( !in_array($name, $this->relations_allowed ) )
continue;
$obj = $m->getRelated($name);
$attrToTake = empty($this->attributes[$name]) ? NULL : $this->attributes[$name];
$related[$name] = $obj instanceof CActiveRecord ? $obj->getAttributes($attrToTake) : $obj;
}
return $related;
}
}