tuks
tuks

Reputation: 790

Yii: change active record field names

I'm new to Yii and I have a table 'Student' with fields like 'stdStudentId', 'stdName', etc. I'm making API, so this data should be returned in JSON. Now, because I want field names in JSON to just be like 'id', 'name', and I don't want all fields returned, i made a method in the model:

public function APIfindByPk($id){
$student = $this->findByPk($id);
return array(
'id'=>$student->stdStudentId, 
'name'=>$student->stdName, 
'school'=>$student->stdSchool
);
}

The problem is, stdSchool is a relation and in this situation, $student->stdSchool returns array with fields like schSchoolId, schName, etc. I don't want fields to be named like that in JSON, and also I don't want all the fields from School returned and I would like to add some fields of my own. Is there a way to do this in Yii, or I'll have to do it manually by writing methods like this?

Upvotes: 1

Views: 1852

Answers (3)

shiji
shiji

Reputation: 1

Override the populateRecord() function of ActiveRecord can achieve this!

My DishType has 5 properties and override the populateRecord function Yii would invoke this when records fetched from db.

My code is here!

class DishType extends ActiveRecord
{
    public $id;
    public $name;
    public $sort;
    public $createTime;
    public $updateTime;


public static function populateRecord($record, $row)
{
    $pattern = ['id' => 'id', 'name' => 'name', 'sort' => 'sort', 'created_at' => 'createTime', 'updated_at' => 'updateTime'];
    $columns = static::getTableSchema()->columns;
    foreach ($row as $name => $value) {
        $propertyName = $pattern[$name];
        if (isset($pattern[$name]) && isset($columns[$name])) {
            $record[$propertyName] = $columns[$name]->phpTypecast($value);
        }
    }
    parent::populateRecord($record, $row);
}

}

Upvotes: 0

crafter
crafter

Reputation: 6297

Since you are getting the values from the database using Yii active record, ask the database to use column aliases.

Normal SQL would be something like the following :

SELECT id AS Student_Number, name AS Student_Name, school AS School_Attending FROM student;

In Yii, you can apply Criteria to the findByPK() function. See here for reference : http://www.yiiframework.com/doc/api/1.1/CActiveRecord#findByPk-detail

$criteria = new CDbCriteria();
$criteria->select = 'id AS Student_Number';
$student = Student::model()->findByPk($id, $criteria);

Note that in order to use a column alias like that, you will have to define a virtual attribute Student_Number in your Student{} model.

Upvotes: 0

darkheir
darkheir

Reputation: 8960

I have been looking for the same thing. There is a great php lib named Fractal letting you achieve it: http://fractal.thephpleague.com/

To explain briefly the lib, for each of your models you create a Transformer that will be doing the mapping between your model attributes and the ones that need to be exposed using the api.

class BookTransformer extends Fractal\TransformerAbstract
{
    public function transform(Book $book)
    {
        return [
            'id' => (int) $book->id,
            'title' => $book->title,
            'year' => $book->yr,
        ];
    }
}

In the transformer you can also set the relation that this model have :

class BookTransformer extends TransformerAbstract
{
    /**
     * List of resources relations that can be used
     *
     * @var array
     */
    protected $availableEmbeds = [
        'author'
    ];

    /**
     * Turn this item object into a generic array
     *
     * @return array
     */
    public function transform(Book $book)
    {
        return [
            'id'    => (int) $book->id,
            'title' => $book->title,
            'year'  => $book->yr,
        ];
    }

    /**
     * Here we are embeding the author of the book
     * using it's own transformer
     */
    public function embedAuthor(Book $book)
    {
        $author = $book->author;

        return $this->item($author, new AuthorTransformer);
    }
}

So at the end you will call

$fractal = new Fractal\Manager();
$resource = new Fractal\Resource\Collection($books, new BookTransformer);
$json = $fractal->createData($resource)->toJson();

It's not easy to describe all the potential of fractal in one answer but you really should give it a try. I'm using it along with Yii so if you have some question don't hesitate!

Upvotes: 1

Related Questions