【问题标题】:using has_one, has_many, and many_many in controller/to filter queries在控制器中使用 has_one、has_many 和 many_many/过滤查询
【发布时间】:2015-06-05 04:34:29
【问题描述】:

我在 silverstripe.org 网站上观看了第 7 课 - 第 10 课的视频,阅读了此页面上的所有文章:http://docs.silverstripe.org/en/3.1/developer_guides/model/,一直在使用 API 并在 silverstripe/stackoverflow 论坛上搜索了几个小时。我真的被困在试图应用我学到的东西上。这就是我想要做的。我想扩展文章持有者和文章页面的概念。我正在尝试创建另一个页面作为主文章持有者,并且我的站点树将按如下方式组织:

HomePage
   |
   | _ MasterArticleHolderOne
   |      |
   |      | _ ArticleHolderA
   |      |      |
   |      |      | _ ArticlePageA1
   |      |      |
   |      |      | _ ArticlePageA2
   |      |      |          
   |      |      | _ ArticlePageA3
   |      |
   |      |
   |      | _ ArticleHolderB
   |      |      |
   |      |      | _ ArticlePageB1
   |      |      |
   |      |      | _ ArticlePageB2
   |      |      |          
   |      |      | _ ArticlePageB3
   |      |
   |      |
   |      | _ ArticleHolderB
   |             |
   |             | _ ArticlePageB1
   |             |
   |             | _ ArticlePageB2
   |             |          
   |             | _ ArticlePageB3
   |       
   | _ MasterArticleHolderTwo

我希望 MasterArticleHolder 页面这样做:在 CMS 中,MasterArticleHolder 页面将有一个选项可以选择任何现有的 ArticleHolder 页面(这意味着即使是上面的 MasterArticleHolderTwo 也可以显示来自 ArticleHolderA 或 B 或 C 的文章)和然后,MasterArticleHolder 页面将显示作为所选 ArticleHolder 页面子级的所有文章。这些文章需要按 PublicationDate 排序;不按他们所属的持有者分组。

这是我目前编写的代码。 ArticlePage 和 ArticleHolder 完美运行。这是我正在努力解决的 MasterArticleHolder(尽管我确实设法至少在 CMS 中为所有现有的 ArticleHolder 页面创建了复选框,但不知道在编写完其他所有内容后它是否会真正起作用):

文章页面

class ArticlePage extends Page {

    private static $db = array(
        'PublicationDate' => 'Date',
    );

    public function getCMSFields() {
        $fields = parent::getCMSFields();

        $fields->addFieldToTab('Root.Main', DateField::create('PublicationDate','Publication Date')->setConfig('showcalendar', true));

        return $fields;
    }
}

文章持有者

class ArticleHolder_Controller extends Page_Controller {

    public function LatestArticles() {
        return ArticlePage::get()
            ->filter('PublicationDate:LessThanOrEqual', SS_Datetime::now())
            ->sort('PublicationDate', 'DESC');
    }
}

MasterArticleHolder

class MasterArticleHolder extends Page {

    private static $many_many = array (
        'Categories' => 'ArticleHolder'
    );

    public function getCMSFields() {
        $fields = parent::getCMSFields();

        $fields->addFieldToTab('Root.Main', CheckboxSetField::create(
            'Categories',
            'Articles to Display',
            ArticleHolder::get()->map('ID','MenuTitle')
        ));

        return $fields;
    }

}
class MasterArticleHolder_Controller extends Page_Controller {

    public function LatestArticles() {
        return ArticlePage::get()
            ->filter(array('PublicationDate:LessThanOrEqual' => SS_Datetime::now()))
            ->sort('PublicationDate', 'DESC')
    }
}

在我看来,可能存在以下关系,但我只是不知道需要哪一个,如果有的话

  • ArticlePage 是 ArticleHolder 的 has_one
  • ArticleHolder 是 ArticlePage 的 has_many
  • ArticleHolder 与 MasterArticleHolder 是一个 many_many(不知道哪个是 belongs_many_many,但我猜是 Article Holder)

以下关系也可能适用,但对我来说似乎不太可能

  • ArticlePage 是一个带有 MasterArticleHolder 的 many_many

现在我通常知道 has_one、has_many 和 many_many 适用于扩展 DataObject 的对象,但我认为由于页面以一种迂回的方式扩展了 DataObject,这些关系可能仍然适用,但我可能完全错了,真的想太多。

希望我能很好地解释自己,让我得到帮助,但不要太多以至于让每个人都不知所措。感谢您的反馈!

【问题讨论】:

    标签: silverstripe


    【解决方案1】:

    您应该进一步了解教程,这(使用 Pages)... 并不是最好的解决方案。它可以工作,但非常复杂,而且不是一个好主意。

    如果您将此作为学习练习,那很酷,但如果不是,则只需使用博客模块http://addons.silverstripe.org/add-ons/silverstripe/blog - 它基本上就是这样做的。

    在本练习中使用 DataObjects 而不是 Pages 会更好。见视频教程 9 (http://www.silverstripe.org/learn/lessons/working-with-data-relationships-has-many)

    一个简单的解决方案是:

    ArticlePage::get()
      ->filter([
        'ParentID'=>$this->Categories()->getIDList(),
        'PublicationDate:LessThanOrEqual'=>'now'
      ])
      ->sort('PublicationDate','desc');
    

    基本上:让父级的每篇文章都是我选择的类别之一(然后是您现有的过滤器、排序等)。

    使用 DataObjects 而不是 Pages 基本上是一样的(Pages 是 DataObjects),但是您会减少对站点树的污染(在 CMS 中)和与子级有关的分层问题等。

    但另一方面,您会失去自动路由以及 Page 为您提供的各种其他功能。这就是为什么如果您不只是想学习,博客模块是一个更好的解决方案。

    【讨论】:

    • 我认为有一个模块可用于我正在尝试做的事情,但我现在使用 silverstripe 所做的很多事情都是试图学习和理解该框架。这就是为什么我选择它而不是 wordpress 或 joomla。我不想仅仅插入代码并让它神奇地工作,我首先想了解所有东西实际上是如何组合在一起的,甚至自己构建一些糟糕的模块版本来加深我的理解。似乎银条对此非常有用。他们的文档很棒。至于你的答案,我会在今晚晚些时候有机会时尝试一下。谢谢!
    【解决方案2】:

    遗憾的是,我没有时间测试这些,但以下应该可以工作.. 至少可以作为指导:

    删除

      private static $many_many = array (
            'Categories' => 'ArticleHolder'
        );
    

    并将类别添加为数据库字段

    private static $db = array(
        'Categories' => 'Varchar'
    );
    

    无需引入新的关系,因为它们已经是该持有者的孩子。复选框字段集将数据存储为逗号分隔列表。这是一个松散的关系,所以请注意。

    然后在过滤器中使用逗号分隔的列表,例如:

    public function LatestArticles() {
    $ids = explode(",", $this->Categories)
    
            return ArticlePage::get()
                ->filter(array('ParentID' => $ids))
                ->sort('PublicationDate', 'DESC')
        }
    

    我只是不记得是数据库字段 parent_id 或 ParentID 还是您可能想要从数据库表中签出的内容。

    【讨论】:

    • 感谢您的帮助,今晚有机会我会试试这个!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-08
    • 1970-01-01
    • 2013-10-22
    • 1970-01-01
    • 2016-05-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多