开发者

How do I achieve virtual attributes in CakePHP (using code, not SQL) as implemented in Ruby on Rails

Source: http://asciicasts.com/episodes/16-virtual-attributes

I'd like to achieve a similar setup as below, but in CakePHP and where the virtual attributes are created using code, not SQL (as documented at http://book.cakephp.org/view/1070/Additional-Methods-and-Properties#Using-virtualFields-1590).

class User < ActiveRecord:开发者_如何学JAVA:Base  
  # Getter  
  def full_name  
    [first_name, last_name].join(' ')  
  end  

  # Setter  
  def full_name=(name)  
    split = name.split(' ', 2)  
    self.first_name = split.first  
    self.last_name = split.last  
  end  
end


As you've rightly mentioned, virtualFields are used to create extra attributes for models using SQL. For generating fields using code, you should try the afterFind method:

function afterFind($results) {
    foreach ($results as $key => $val) {
        if (isset($val['User']['first_name']) && isset($val['User']['last_name'])) {
            $results[$key]['User']['full_name'] = $this->formatName($val['User']['first_name'], $val['User']['last_name']);
        }
    }
    return $results;
}

function formatName($firstName, $lastName) {
    $firstName = trim($firstName);
    $lastName = trim($lastName);
    return $lastName . ', ' . $firstName;
}

You can read more on this from the book here. I'd assume you'll have to test this a little further, and probably include the afterFind method's second parameter $primary.


EDIT: I just realized that another way of doing this would be to include such functions directly in your model:

function getFullName($user = null) {
    if ($user) {
        $this->set($user);
    }
    return $this->data['User']['first_name'] . ' ' . $this->data['User']['last_name'];
}

And there's your getter!


You can use beforeSave and afterFind callback. Here is my code:

class User extends AppModel {

    // Setter
    function beforeSave() {
        if(!empty($this->data['User']['full_name'])) {
            list($this->data['User']['first_name'], $this->data['User']['last_name']) = explode(" ", $this->data['User']['full_name']);
        }

        return true
    }

    // Getter
    function afterFind(array $results, bool $primary) {
        foreach($results as $key => $result) {
            $result['User']['full_name'] = $result['User']['first_name'] + " " + $result['User']['last_name'];

            $results[$key] = $result;
        }

        return $results;
    }
} 

But I think SQL concat will be faster than PHP string concat. So I think (if you can) using virtual fields will be better.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜