跳到内容

模型

编辑此页

您决定继续阅读关于 Symfony CMF 的内容 10 分钟?真是好消息!在这一部分,您将更多地了解 CMF 的默认数据库层。

注意

再次声明,本章讨论的是 PHPCR 存储层。但是 CMF 是以存储不可知的方式编写的,这意味着它不与特定的存储系统绑定。

熟悉 PHPCR

PHPCR 将所有数据存储到一个大的树结构中。您可以将其比作文件系统,其中每个文件和目录都包含数据。这意味着使用 PHPCR 存储的所有数据都与至少另一个数据(其父数据)存在关系。反向关系也存在,您也可以获取数据元素的子元素。

让我们看一下您在前一章中下载的 CMF Sandbox 的树的转储。转到您的目录并执行以下命令

1
$ php bin/console doctrine:phpcr:node:dump

结果将是 PHPCR 树

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
ROOT:
    cms:
        menu:
            main:
                admin-item:
                projects-item:
                    cmf-item:
                company-item:
                    team-item:
            ...
        content:
            home:
                phpcr_locale:en:
                phpcr_locale:fr:
                phpcr_locale:de:
                seoMetadata:
                additionalInfoBlock:
                    child1:
            ...
        routes:
            en:
                company:
                    team:
                    more:
                about:
            ...

每个数据在 PHPCR 中都称为节点。所有内容都附加在 ROOT 节点下(由 PHPCR 本身创建)。

每个节点都有属性,其中包含数据。您为页面设置的内容、标题和标签都保存在 home 节点的此类属性中。您可以通过将 --props 开关添加到 dump 命令来查看这些属性

1
$ php bin/console doctrine:phpcr:node:dump --props /cms/content/home

注意

之前,PHPCR 树被比作文件系统。虽然这让您对发生的事情有一个很好的了解,但这并不是唯一的真相。您可以将其比作 XML 文件,其中每个节点都是一个元素,其属性是属性。

Doctrine PHPCR-ODM

Symfony CMF 使用 Doctrine PHPCR-ODM 与 PHPCR 交互。Doctrine 允许用户创建对象(称为文档),这些对象直接持久化到 PHPCR 树并从中检索。这类似于 Symfony 标准版中默认提供的 Doctrine ORM,但用于 PHPCR 而不是 SQL 数据库。

从代码创建内容

现在您对 PHPCR 有了更多了解,并且您了解了与之交互的工具,您可以开始自己使用它了。在前一章中,您通过使用 Yaml 文件编辑页面,该文件由沙盒的 fixture 加载器解析。这一次,您将使用 PHP 代码创建一个页面。

首先,您必须创建一个新的 DataFixture 以添加您的新页面。您可以通过在 AppBundle 中创建一个新类来完成此操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// src/AppBundle/DataFixtures/PHPCR/LoadQuickTourData.php
namespace AppBundle\DataFixtures\PHPCR;

use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;

class LoadQuickTourData implements FixtureInterface, OrderedFixtureInterface
{
    public function getOrder()
    {
        // refers to the order in which the class' load function is called
        // (lower return values are called first)
        return 100;
    }

    public function load(ObjectManager $documentManager)
    {
        // you will add code to this method in the next steps
    }
}

$documentManager 是将文档持久化到 PHPCR 的对象。但首先,您必须创建一个新的 Page 文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use Doctrine\ODM\PHPCR\DocumentManager;
use Symfony\Cmf\Bundle\ContentBundle\Doctrine\Phpcr\StaticContent;

// ...
public function load(ObjectManager $documentManager)
{
    if (!$documentManager instanceof DocumentManager) {
        throw new \RuntimeException(sprintf(
            'Fixture requires a PHPCR ODM DocumentManager instance, instance of "%s" given.',
            get_class($documentManager)
        ));
    }

    $content = new StaticContent();
    $content->setName('quick-tour'); // the name of the node
    $content->setTitle('Quick tour new Page');
    $content->setBody('I have added this page myself!');
}

每个文档都需要一个父文档。在本例中,父文档应该是内容根节点。为此,我们首先从 PHPCR 检索根文档,然后将其设置为其父文档

1
2
3
4
5
6
7
public function load(ObjectManager $documentManager)
{
    // ...
    // get the root document
    $contentRoot = $documentManager->find(null, '/cms/content');
    $content->setParentDocument($contentRoot); // set the parent to the root
}

最后,我们必须告诉 Document Manager 使用 Doctrine API 持久化我们的内容文档

1
2
3
4
5
6
public function load(ObjectManager $documentManager)
{
    // ...
    $documentManager->persist($content); // tell the document manager to track the content
    $documentManager->flush(); // doctrine is like a toilet: never forget to flush
}

现在您需要再次执行 doctrine:phpcr:fixtures:load 命令。再次转储节点时,您的新页面应显示在 /cms/content/quick-tour 下!

另请参阅

如果您想了解更多关于在 Symfony 应用程序中使用 PHPCR 的信息,请参阅 Doctrine PHPCR-ODM

最终想法

PHPCR 是在 CMS 中存储页面的强大方法。但是,如果您不熟悉它,您可以随时切换到另一个存储层。

回顾这 20 分钟,您应该已经学会了如何使用新的存储层,并且您已经添加了 2 个新页面。您是否看到当使您的应用程序可编辑时,CMF 是多么容易工作?它提供了您以前必须自己做的大部分事情。

但您现在只看到了 CMF 的一小部分,还有更多内容需要学习,并且还有许多其他扩展包在等待着您。在您可以完成所有这些操作之前,您应该了解 CMF 的主干:路由系统。您可以在下一章中阅读相关内容。准备好再来 10 分钟了吗?

本作品,包括代码示例,根据 Creative Commons BY-SA 3.0 许可协议获得许可。
目录
    版本