Chinaunix首页 | 论坛 | 博客
  • 博客访问: 963742
  • 博文数量: 335
  • 博客积分: 10287
  • 博客等级: 上将
  • 技术积分: 3300
  • 用 户 组: 普通用户
  • 注册时间: 2005-08-08 15:29
文章分类

全部博文(335)

文章存档

2015年(4)

2014年(15)

2013年(17)

2012年(11)

2011年(12)

2010年(96)

2009年(27)

2008年(34)

2007年(43)

2006年(39)

2005年(37)

我的朋友

分类:

2007-09-14 16:10:00

回调

我们已经加入了一些model回调(函数),它们允许你在某个model操作前或后悄悄的加点逻辑在里面。为了在应用程序中使用本功能,使用提供的参数,并且在Cake Model里覆盖这些函数。

beforeFind

  • string $conditions

beforeFind()回调函数仅在一个查找操作之前执行。可以在本方法里放入任何预先查找的逻辑。当你在model里覆盖时,如果你想执行查找,返回true,若是想取消,返回false

afterFind

  • array $results

使用本回调会修改一个查询操作返回的结果,或者进行其他的post查找逻辑。Model查找操作返回的结果就是本函数的参数,并且返回值就是修改的结果。

beforeValidate

model验证前使用此回调修改model数据。它也能用来增加额外的,更加复杂的验证规则,使用Model::invalidate()验证。在本上下文中,model数据可以通过$this->data访问。本函数也必须返回true,否则save()执行会终止。

beforeSave

在本函数中加入任何预保存的逻辑。本函数在model 数据验证后(假设它一验证,否则save()调用取消,并且本回调不会执行)立即执行。但是在数据保存之前,如果你想保存工作本函数也会返回true,本函数也应该返回true,如果你想让保存操作继续,如果取消,则返回false

beforeSave的一个用法可以是格化式指定数据库引擎上的时间数据。

/ Date/time fields created by HTML Helper:

// This code would be seen in a view

 

$html->dayOptionTag('Event/start');

$html->monthOptionTag('Event/start');

$html->yearOptionTag('Event/start');

$html->hourOptionTag('Event/start');

$html->minuteOptionTag('Event/start');

 

/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/

 

// Model callback functions used to stitch date

// data together for storage

// This code would be seen in the Event model:

 

function beforeSave()

{

    $this->data['Event']['start'] = $this->_getDate('Event', 'start');

 

    return true;

}

 

function _getDate($model, $field)

{

    return date('Y-m-d H:i:s', mktime(

        intval($this->data[$model][$field . '_hour']),

        intval($this->data[$model][$field . '_min']),

        null,

        intval($this->data[$model][$field . '_month']),

        intval($this->data[$model][$field . '_day']),

        intval($this->data[$model][$field . '_year'])));

}

  • afterSave

在本回调方法中,每次保存之后放入你想执行的任何逻辑。

  • beforeDelete

在本函数中放置任何预删除逻辑。如果你想让删除操作继续的话,本函数应该返回true。否则你想终止的话则返回false

  • afterDelete

在本回调方法里,每个删除操作之后,放置你想执行的任何逻辑。

变量

当创建model时,你需要设置某些特定的变量来访问Cake的功能:

$primaryKey

如果model和一个数据库表相对应,并且表的主键的命名不是”id”,那么使用本变量告诉Cake你的主键名。

$recursive

它将设置Cake使用find()和findAll()操作获取相关联model数据的层数。

假想你有一个组(Group),每组有许多用户(User),而这些用户又有很多文章(Article)。

Model::recursive 选项

$recursive = 0

Cake 获取Group

$recursive = 1

Cake 获取Group以及相关联的Users

$recursive = 2

Cake 获取Group, 相关联的Users, 以及Users关联的Articles

$transactional

告诉Cake是否为本model启用事务(例如,begin/commit/rollback)。设置为一个布尔值。仅当数据库支持时。[1]

$useTable

如果你想使用的数据库表不是复数格式的model名(以及你不打算修改表名),将本变量设置为你想让model使用的表名。

$validate

用来验证传递到model的数据。参看第12章。

$useDbConfig

记住了在/app/config/database.php配置的数据库设置了吗?使用本变量来切换他们-使用在数据库配置文件里创建的数据库链接变量的名称。你已经猜到,缺省的是‘defualt’

CakePHP最厉害的特性之一就是Model提供的关系映射。在CakePHP中,表之间的关系是通过关联处理的。关联就是相关逻辑单元之间的胶水。

CakePHP4中关联:

1.    hasOne

2.    hasMany

3.    belongsTo

4.    hasAndBelongsToMany

当定义model之间的关系时,Cake会自动获取与正在工作的model相关的model。例如,如果一个Post ModelAuthor Model相关,并使用hasMany关联,调用Controller$this->Post->findAll()将会获得Post记录,同时也会获得与他们相关的Author记录。

为正确使用关联,建议遵循CakePHP命名规则(参考附录)。如果你使用了CakePHP的命名规则,你也可以使用scaffolding可视化你的应用数据,因为scaffolding检测并使用model之间的关联。当然,在没遵循Cake的命名规则时,你也可以一直自定义model关联来进行工作,但我们会在后面说明一些技巧。现在,让我们盯住这些规则吧。在这里我们关心的命名规则是主键,Model名,以及表名。

下面是Cake期望这些不同元素名称的概览:(参看附录获取更多关于命名的信息):

1.    外键:【单数model名】_id.例如,可以将指回到Author属于的Post的“author”表的外键命名为”post_id”.

2.    表名:【复数的对象名】,因为我们想存储Blog post和作者的信息,表名应该分别为"posts" "authors"

3.    Model名:【骆驼峰命名,表名的单数形式】。"posts" 表的Model名为"Post""authors"表的model名为"Author"

CakePHPScaffolding希望你的关联与你的列保持同样的顺序。因此如果你有一个Article belongsTo(属于)3个其他的modelAuthor, Editor, Publisher),你需要3个键:uthor_id, editor_id, Publisher_id.Scaffolding期望你的关联和表中的键保持一样的顺序(例如,第一个是Author,第二个是Editor,最后是Publisher)。

为了描述这些关联如何工作,让我们继续使用Blog应用程序作为实例吧。假设我们打算为blog创建一个简单的用户管理系统。也假设它会在不跟踪Users的情况下进行,但是我们希望每个用户都有一个关联的ProfileUser hasOne Profile.Users也会创建留言并且保留他们的关联(User hasMany Comments),一旦我们让用户系统运行,我们会将视线转移到使用hasAndBelongsToMany(Post hasAndBelongsToMany Tags)Posts以及与其相关的Tag对象。

为建立关联,我们假设你已经创建了User以及Profile Model。为了定义他们的hasOne关联,我们需要为Model增加一个数组告诉Cake它们是怎样关联的。这里是它们如何关联的:

/app/models/user.php hasOne

class User extends AppModel

{

    var $name = 'User';

    var $hasOne = array('Profile' =>

                        array('className'    => 'Profile',

                              'conditions'   => '',

                              'order'        => '',

                              'dependent'    =>  true,

                              'foreignKey'   => 'user_id'

                        )

                  );

}

?>

$hasOne数组是Cake用来创建UserProfile model之间的关联的。数组中的每个键允许你更进一步的配置关联:

1.    className (必须): 关联的model 类名。

例如,我们会指定'Profile' model类名。

2.    conditions: SQL条件部分,它定义了关系。

我们可能会使用它来告诉Cake只关联Profile,此Profile有一个绿色的标记头,如果我们愿意。为了定义这个条件,可以为此键指定一个SQL条件作为其值:”Profile.header_color = 'green'"

3.    order:关联model的顺序

例如,如果你想让你的关联model以某顺序排列,为此键设置一个SQL排序谓语:"Profile.name ASC"

4.    dependent:如果设置为true,当它销毁时,相关联的model也会销毁。

例如,如果"Cool Blue"Profile"Bob"相关联,并且我们删除用户"Bob","Cool Blue"Profile也会删除。

5.    foreignKey:指向关联的model的外键名。

在这里,你正在操作一个没有遵循Cake命名规则的数据库。

现在,当使用Profile model来执行 find()findAll()时,我们应该也看到相关联的User model:

$user = $this->User->read(null, '25');

print_r($user);

 

//输出:

 

Array

(

    [User] => Array

        (

            [id] => 25

            [first_name] => John

            [last_name] => Anderson

            [username] => psychic

            [password] => c4k3roxx

        )

 

    [Profile] => Array

        (

            [id] => 4

            [name] => Cool Blue

            [header_color] => aquamarine

            [user_id] = 25

        )

)

如果User想看到他的Profile,我们需要定义一个关联,因此Profile可以看见他自己的User。在Cake里,可以使用belongsTo关联实现。在Profile model里,我们可以如下操作:

/app/models/profile.php belongsTo

class Profile extends AppModel

{

    var $name = 'Profile';

    var $belongsTo = array('User' =>

                           array('className'  => 'User',

                                 'conditions' => '',

                                 'order'      => '',

                                 'foreignKey' => 'user_id'

                           )

                     );

}

?>

$belongsTo数组是Cake用来创建UserProfile model之间的关联的。数组中的每个键允许你更进一步的配置关联:

1.    className (必须):你想要关联的model的类名

例如:我们想指定‘User’model 类名。

2.    conditions:定义关系的SQL条件语句

我们可以使用它告诉Cake仅关联活动的User。为了实现它,将键值设置为"User.active = '1'"或者其他类似的。

3.    order:关联model的顺序。

如果你想让你的关联model以某顺序排列,为此键设置一个SQL排序谓语:"User.last_name ASC"

6.    foreignKey: 指向关联model的外键名。

在这里,你正在操作一个没有遵循Cake命名规则的数据库。

现在,当使用Profile model执行 find()findAll(),我们应该也可以看到相关联的User model:

$profile = $this->Profile->read(null, '4');

print_r($profile);

 

//output:

 

Array

(

 

    [Profile] => Array

        (

            [id] => 4

            [name] => Cool Blue

            [header_color] => aquamarine

            [user_id] = 25

        )

 

    [User] => Array

        (

            [id] => 25

            [first_name] => John

            [last_name] => Anderson

            [username] => psychic

            [password] => c4k3roxx

        )

)

 

尽管UserProfile model已经关联,并且工作正常,让我们再构建我们的系统,以至User记录和Comment记录关联。在User model中可以如下定义:

/app/models/user.php hasMany

class User extends AppModel

{

    var $name = 'User';

    var $hasMany = array('Comment' =>

                         array('className'     => 'Comment',

                               'conditions'    => 'Comment.moderated = 1',

                               'order'         => 'Comment.created DESC',

                               'limit'         => '5',

                               'foreignKey'    => 'user_id',

                               'dependent'     => true,

                               'exclusive'     => false,

                               'finderQuery'   => ''

                         )

                  );

 

    // Here's the hasOne relationship we defined earlier...

    var $hasOne = array('Profile' =>

                        array('className'    => 'Profile',

                              'conditions'   => '',

                              'order'        => '',

                              'dependent'    =>  true,

                              'foreignKey'   => 'user_id'

                        )

                  );

}

?>

$hasMany数组是Cake用来创建UserComment model之间的关联的。数组中的每个键允许你更进一步的配置关联:

1.    className(必须):你想要关联的model的类名

例如:我们想指定‘Comment’model 类名。

2.    conditions: 定义关系的SQL条件语句

我们可以使用它告诉Cake仅关联通过管理的Comment。为了实现它,将键值设置为" Comment.moderated = 1"或者其他类似的。

3.    order: 关联model的顺序。

如果你想让你的关联model以某顺序排列,为此键设置一个SQL排序谓语:"Comment.created DESC "

4.    limit:你想让Cake获取关联model的最大数

在本例,我们不会获取所有用户的留言,仅仅为5.

5.    foreignKey: 指向关联model的外键名。

在这里,你正在操作一个没有遵循Cake命名规则的数据库。

6.    dependent:如果设置为true,当它销毁时,相关联的model也会销毁。

例如,如果"Cool Blue"Profile"Bob"相关联,并且我们删除用户"Bob","Cool Blue"Profile也会删除。

7.    exclusive:如果设置为true,所有关联的对象在没有让beforeDelete回调运行时在一个SQL语句中会被删掉,

对于比较简单的关联,使用起来很好,因为它能更快。

8.    finderQuery:指定一个完整的SQL语句获取关联。

对于复杂的依赖多个表的关联,这是一种优秀的方法。如果Cake的自动关联不工作,在这里,你可以定义它。

现在,当使用User model执行 find()findAll(),我们应该也可以看到相关联的Comment model:

$user = $this->User->read(null, '25');

print_r($user);

 

//输出:

 

Array

(

    [User] => Array

        (

            [id] => 25

            [first_name] => John

            [last_name] => Anderson

            [username] => psychic

            [password] => c4k3roxx

        )

 

    [Profile] => Array

        (

            [id] => 4

            [name] => Cool Blue

            [header_color] => aquamarine

            [user_id] = 25

        )

 

    [Comment] => Array

        (

            [0] => Array

                (

                    [id] => 247

                    [user_id] => 25

                    [body] => The hasMany assocation is nice to have.

                )

 

            [1] => Array

                (

                    [id] => 256

                    [user_id] => 25

                    [body] => The hasMany assocation is really nice to have.

                )

 

            [2] => Array

                (

                    [id] => 269

                    [user_id] => 25

                    [body] => The hasMany assocation is really, really nice to have.

                )

 

            [3] => Array

                (

                    [id] => 285

                    [user_id] => 25

                    [body] => The hasMany assocation is extremely nice to have.

                )

 

            [4] => Array

                (

                    [id] => 286

                    [user_id] => 25

                    [body] => The hasMany assocation is super nice to have.

                )

 

        )

)

在这里,当我们不打算记录处理过程时,定义"Comment belongsTo User"关联也是一个相当不错的注意,因此2model都能看到对方。当你试图使用scaffolding时,未定义2model之间的关联常常是一个常见的难题。

阅读(1445) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~