4.8 创建、修改和保存关系记录

假设你要获取一条博客记录,并且想操作它的关系记录和记录集。你只需要获取或者设置关系属性即可;如果它存在于数据库中,Solar模型会自动构建它;如果它不存在于数据库中,你将得到一条新的记录或一个新的记录集。

<?php
/**
 * @var Solar_Sql_Model_Catalog $model
 */

// get the blog item
$item = $model->blogs->fetch(1);

// look at its related summary record. this will
// create a new summary record on-the-fly if one
// does not already exist.
echo htmlspecialchars($item->summary->last_comment_at);

// loop through its comments collection. this will
// create a new empty collection if one does not
// already exist.
if ($item->comments->isEmpty()) {
    echo "No comments.";
} else {
    foreach ($item->comments as $n => $comment) {
        echo "Comment $n is by "
           . htmlspecialchars($comment->author)
           . "<br />";
    }
}

但是,Solar模型不会为你自动构建”属于“关系属性。因为关系记录优先于本地记录,所以你必须手动创建和并绑定它。

<?php
/**
 * @var Solar_Sql_Model_Catalog $model
 */

// get the blog item
$item = $model->blogs->fetch(1);

// blog belongsTo author ... do we have an author here?
if (! $item->author) {
    $author = $model->authors->fetchByHandle('pmjones');
    $item->author = $author;
}

对于“有多”关系的记录集,你可以直接在记录集后面创建属性,无需从关系模型中创建新记录并绑定属性。

<?php
/**
 * @var Solar_Sql_Model_Catalog $model
 * @var Acme_Model_Blog_Record $item
 */
if (! $item->comments) {
    $item->setNewRelated('comments');
}

// you could do this to add a new comment:
$comment = $model->comments->fetchNew();
$comment->body = "A new comment.";
$item->comments[] = $comment;

// but this may be easier:
$comment = $item->comments->appendNew(array(
    'body' => "A new comment.",
));

要保存一条记录及它所有的从属记录和记录集,你可以调用那条记录的save()方法。但这不会保存优先级更高的“属于”记录;因此,你要手动保存它们。

<?php
/**
 * @var Acme_Model_Blog_Record $item
 */

// set a value on the related summary record
$item->summary->last_comment_at = date('Y-m-d H:i:s');

// save the blog record, including all subordinate
// has-one, has-many, and has-many-through relateds
$item->save();

// the $item->author property will not be saved;
// it is a superior belongs-to related, not a subordinate

4.8.1 自动外键管理

对于“有一”和“有多”关系来说,当你保存记录时,Solar模型系统会在关系记录和记录集中自动为你设置合适的外键。

但是,如果你有一个新的“属于”关系记录,在你保存从属记录之前,你要先手动保存它。这是因为从属记录所属的(高优先级的)记录没有主键。如果你当前正在保存某条记录,但它所属的记录在数据库中不存在,那么它将会抛出一个异常。

最后,在“间接有多”关系中,Solar模型系统会为你管理关联映射表。你只需要向外地记录集添加记录即可。Solar模型系统会按需创建记录集中不存在的记录。如果从记录集中移除一条记录,那么映射表中相应的记录也会被移除,但不会影响外地表。

<?php
/**
 * @var Solar_Sql_Model_Catalog $model
 * @var Acme_Model_Blog_Record $item
 */

// get all the existing tags
$tags = $model->tags->fetchAll();

// add the first three tags in the tags table
// to the blog item
$item->tags[0] = $tags[0];
$item->tags[1] = $tags[1];
$item->tags[2] = $tags[2];

// save the blog item; solar will manage the taggings table
// for you automatically, adding and removing mappings in
// that table as needed.
$item->save();

4.8.2 独立操作

如果你不想的话,你可以不使用关系来操作记录。你可以总是使用模型获取记录,并且独立地操作记录和记录集。但是,你将不得不自己管理外键。

<?php
/**
 * @var Solar_Sql_Model_Catalog $model
 */

// the blog ID to work with
$blog_id = 1;

// get the comments on the blog ID
$comments = $model->comments->fetchAll(array(
    'where' => array(
        'blog_id = ?' => $blog_id,
    ),
));

// add a new comment
$comments->appendNew(array(
    'body' => 'This is my new comment.',
    'blog_id' => $blog_id,
));

// save the collection
$comments->save();