在 controller/to 过滤器查询中使用 has_one、has_many 和 many_many
using has_one, has_many, and many_many in controller/to filter queries
我在 silverstripe.org 网站上观看了第 7 课 - 第 10 课的视频,阅读了此页面上的所有文章:http://docs.silverstripe.org/en/3.1/developer_guides/model/,都在 API 中并且在 silverstripe/Whosebug 论坛上搜索了几个小时。我真的很难尝试应用我学到的东西。这是我正在尝试做的。我想扩展文章持有者和文章页面的概念。我正在尝试制作另一个作为主文章持有者的页面,我的站点树将按如下方式组织:
HomePage
|
| _ MasterArticleHolderOne
| |
| | _ ArticleHolderA
| | |
| | | _ ArticlePageA1
| | |
| | | _ ArticlePageA2
| | |
| | | _ ArticlePageA3
| |
| |
| | _ ArticleHolderB
| | |
| | | _ ArticlePageB1
| | |
| | | _ ArticlePageB2
| | |
| | | _ ArticlePageB3
| |
| |
| | _ ArticleHolderB
| |
| | _ ArticlePageB1
| |
| | _ ArticlePageB2
| |
| | _ ArticlePageB3
|
| _ MasterArticleHolderTwo
我希望 MasterArticleHolder 页面这样做:在 CMS 中,MasterArticleHolder 页面将有一个选项可以 select 任何现有的 ArticleHolder 页面(这意味着即使是上面的 MasterArticleHolderTwo 也可以显示来自 ArticleHolderA 的文章或 B 或 C),然后 MasterArticleHolder 页面将显示所有作为 selected ArticleHolder 页面子级的文章。这些文章需要按 PublicationDate 排序;没有按他们所属的持有人分组。
这是我到目前为止编写的代码。 ArticlePage 和 ArticleHolder 工作完美。这是我正在努力解决的 MasterArticleHolder(尽管我确实设法至少为所有现有的 ArticleHolder 页面创建了出现在 CMS 中的复选框,不知道它是否会在其他所有内容写入后实际运行):
文章页数
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 是一个 has_one with ArticleHolder
- ArticleHolder 是 has_many 和 ArticlePage
- ArticleHolder 是 many_many 和 MasterArticleHolder(不知道哪个属于 belongs_many_many 但我猜是 ArticleHolder)
以下关系也可能适用,但对我来说不太可能
- ArticlePage 是一个 many_many with MasterArticleHolder
现在我通常知道 has_one、has_many 和 many_many 适用于扩展 DataObject 的对象,但我认为由于页面以一种迂回的方式扩展了 DataObject这些关系可能仍然适用,但我可能完全错了,真的想得太多了。
希望我对自己的解释足够好,以便获得帮助,但又不会让所有人不知所措。感谢反馈!
您应该深入学习教程,这(使用 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 基本上是一样的(页面是 DataObjects),但是站点树(在 CMS 中)的污染和与子项有关的层次结构问题等更少。
但另一方面,您失去了自动路由以及佩奇为您提供的各种其他功能。这就是为什么如果您不只是想学习的话,博客模块是更好的解决方案。
遗憾的是,我没有时间测试这些,但以下内容应该有效.. 至少作为指南:
删除
private static $many_many = array (
'Categories' => 'ArticleHolder'
);
并将类别添加为数据库字段
private static $db = array(
'Categories' => 'Varchar'
);
无需引入新关系,因为它们已经是该持有人的 Children。复选框字段集将数据存储为逗号分隔列表。这是一个松散的关系,所以请注意。
然后在过滤器中使用逗号分隔列表,例如:
public function LatestArticles() {
$ids = explode(",", $this->Categories)
return ArticlePage::get()
->filter(array('ParentID' => $ids))
->sort('PublicationDate', 'DESC')
}
我只是不记得是数据库字段 parent_id 或 ParentID 还是什么,所以您可能想从数据库表中检出。
我在 silverstripe.org 网站上观看了第 7 课 - 第 10 课的视频,阅读了此页面上的所有文章:http://docs.silverstripe.org/en/3.1/developer_guides/model/,都在 API 中并且在 silverstripe/Whosebug 论坛上搜索了几个小时。我真的很难尝试应用我学到的东西。这是我正在尝试做的。我想扩展文章持有者和文章页面的概念。我正在尝试制作另一个作为主文章持有者的页面,我的站点树将按如下方式组织:
HomePage
|
| _ MasterArticleHolderOne
| |
| | _ ArticleHolderA
| | |
| | | _ ArticlePageA1
| | |
| | | _ ArticlePageA2
| | |
| | | _ ArticlePageA3
| |
| |
| | _ ArticleHolderB
| | |
| | | _ ArticlePageB1
| | |
| | | _ ArticlePageB2
| | |
| | | _ ArticlePageB3
| |
| |
| | _ ArticleHolderB
| |
| | _ ArticlePageB1
| |
| | _ ArticlePageB2
| |
| | _ ArticlePageB3
|
| _ MasterArticleHolderTwo
我希望 MasterArticleHolder 页面这样做:在 CMS 中,MasterArticleHolder 页面将有一个选项可以 select 任何现有的 ArticleHolder 页面(这意味着即使是上面的 MasterArticleHolderTwo 也可以显示来自 ArticleHolderA 的文章或 B 或 C),然后 MasterArticleHolder 页面将显示所有作为 selected ArticleHolder 页面子级的文章。这些文章需要按 PublicationDate 排序;没有按他们所属的持有人分组。
这是我到目前为止编写的代码。 ArticlePage 和 ArticleHolder 工作完美。这是我正在努力解决的 MasterArticleHolder(尽管我确实设法至少为所有现有的 ArticleHolder 页面创建了出现在 CMS 中的复选框,不知道它是否会在其他所有内容写入后实际运行):
文章页数
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 是一个 has_one with ArticleHolder
- ArticleHolder 是 has_many 和 ArticlePage
- ArticleHolder 是 many_many 和 MasterArticleHolder(不知道哪个属于 belongs_many_many 但我猜是 ArticleHolder)
以下关系也可能适用,但对我来说不太可能
- ArticlePage 是一个 many_many with MasterArticleHolder
现在我通常知道 has_one、has_many 和 many_many 适用于扩展 DataObject 的对象,但我认为由于页面以一种迂回的方式扩展了 DataObject这些关系可能仍然适用,但我可能完全错了,真的想得太多了。
希望我对自己的解释足够好,以便获得帮助,但又不会让所有人不知所措。感谢反馈!
您应该深入学习教程,这(使用 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 基本上是一样的(页面是 DataObjects),但是站点树(在 CMS 中)的污染和与子项有关的层次结构问题等更少。
但另一方面,您失去了自动路由以及佩奇为您提供的各种其他功能。这就是为什么如果您不只是想学习的话,博客模块是更好的解决方案。
遗憾的是,我没有时间测试这些,但以下内容应该有效.. 至少作为指南:
删除
private static $many_many = array (
'Categories' => 'ArticleHolder'
);
并将类别添加为数据库字段
private static $db = array(
'Categories' => 'Varchar'
);
无需引入新关系,因为它们已经是该持有人的 Children。复选框字段集将数据存储为逗号分隔列表。这是一个松散的关系,所以请注意。
然后在过滤器中使用逗号分隔列表,例如:
public function LatestArticles() {
$ids = explode(",", $this->Categories)
return ArticlePage::get()
->filter(array('ParentID' => $ids))
->sort('PublicationDate', 'DESC')
}
我只是不记得是数据库字段 parent_id 或 ParentID 还是什么,所以您可能想从数据库表中检出。