lekoala / silverstripe-blocks
使用SilverStripe中的块构建页面
Requires
- php: ^7.4 || ^8
- bummzack/sortablefile: ^2
- silverstripe/recipe-cms: ^4.4 || ^5
- silverstripe/recipe-plugin: ^1 || ^2
- symbiote/silverstripe-gridfieldextensions: ^3.1 || ^4
Requires (Dev)
- phpunit/phpunit: ^9.5
- squizlabs/php_codesniffer: ^3.5
This package is auto-updated.
Last update: 2024-09-12 11:51:16 UTC
README
简介
块页面
允许使用“块”内容模块化页面。这旨在成为elemental模块的一个简单替代品。
所有内容都保存在内容字段中,因此可以无性能损失地使用。
与块一起工作
我们有一个块页面,允许通过块来管理内容,而不是大型的“内容”部分
我们有一个默认块,即“内容块”,允许设置标题、内容和图片
块都是相同的DataObject:Block.php中的内容以json格式存储,因此不需要创建此类的扩展。相反,我们只需创建使用不同模板进行渲染的新类型的块。
创建新的块类型
通常,您想基于给定的HTML内容集成一些新的块
在
/app/templates/Blocks/MyNewBlock.ss
然后您可以调用任务
/dev/tasks/BlocksCreateTask
如果缺失,它将创建php类并在您的主题中创建scss样式,前提是您有scss目录
使用流畅字段构建器
由于数据存储在json块中,因此添加字段不太方便
您可以使用此手动完成
$fields->push(new TextField('BlockData[Title]', 'Title'));
但是,调用这个BlockData[Title]东西真的很丑
相反,您可以有一个更漂亮的
$fields->addText('Title');
请参阅BlockFieldList以获取所有可用方法,它应该涵盖大多数常见情况。对于高级使用,您可能需要在项目中扩展它以处理自定义字段类型
默认情况下,图片字段是可见的(从BaseBlock继承)。如果您发现这不方便,请随时删除它
$fields->removeByName('Image');
警告:作为安全措施,避免与现有的Block.php字段(如Content)命名冲突。这就是为什么在addEditor()中的默认值是"Description"。
数据和设置
有两个选项卡:主选项卡和设置选项卡。基本上,主选项卡中的任何内容都应该可本地化,而设置选项卡中的任何内容都应该是固定的。
为了添加设置,您可以在设置选项卡中添加字段,如下所示
$fields->addSettings(function (BlockFieldList $fields) {
$fields->addCheckbox('MySetting');
});
基本上,此辅助程序所做的只是将流畅构建器的键设置为设置,将当前选项卡设置为设置,然后重置一切。
处理基本集合(即项目)
对于基本集合,我们仍然可以在我们的json blob中存储所有内容
在这个例子中,我添加了3个项目,具有名称、电子邮件、描述和图片
foreach (range(1, 3) as $i) {
$fields->addHeader("Item $i");
$fields->addText([$i, 'Name']);
$fields->addText([$i, 'Email']);
$fields->addEditor([$i,'Description']);
$fields->addUpload([$i, 'ImageID'], "Image"); // don't forget the ID suffix
}
请注意我们使用的[]数组表示法。我们不是将名称作为字符串传递,而是将一个包含索引和名称的数组作为第二个参数传递。我们的BlockFieldList知道如何处理这种情况。
您可以通过我们的特殊$Items(在Blocks.php中定义为const ITEM_KEYS)自由循环它们。如果用于块中,则自动发布资产(文件和图片)
<% loop $Items %>
<div class="col col-$Columns" id="item-$Counter">
$Name <$Email><br/>
$Description
<img src="$Image.Link">
</div>
<% end_loop %>
它包括默认迭代器值(FirstLast、Pos),但也包括特殊值(Total、Counter和Columns)。
- Total:集合中的项目总数
- Counter:页面中的项目总数
- Columns:基于12列的数字(非常适合Bootstrap等使用)
太棒了!
处理文件和图片
默认情况下,每个块都有一个many_many的文件和图片。您可以使用以下方式轻松添加这些字段
$fields->addImages();
或
$fields->addFiles();
对滑块、附加文档等很有用
这些默认可排序,归功于 bummzack/sortablefile,并且可以在模板中使用
<% loop $SortedImages %>
<% end_loop %>
处理关系
您可能想知道这些在做什么
public function Collection()
{
return false;
}
public function SharedCollection()
{
return false;
}
它们默认返回 false,以避免在模板中产生任何问题。但根据您的块的功能,它们可以返回任何相关的 DataList 或 ArrayList。
例如,用于显示最新博客文章的块可能如下所示
public function SharedCollection()
{
return BlogPost::get()->limit(3);
}
请注意 Collections 和 SharedCollections 之间的区别
- Collection:数据根据给定的块进行筛选。它是特定的,需要从 DataObject 到块的 has_one 关系
- SharedCollection:对于此类别的所有块,数据是相同的
其他模板内容
菜单
您可以使用以下代码片段生成锚点基本菜单。每个块都可以有自己的 id(设置选项卡,基于 MenuTitle,如果为空)
<ul>
<% loop MenuAnchorsItems %>
<li><a href="$Link">$Title</a></li>
<% end_loop %>
</ul>
覆盖默认内容块
您可以通过在 /app/templates/Blocks/ContentBlock.ss 中添加自己的模板来轻松覆盖默认模板
默认模板是
$Description.RAW
<% if Image %>
$Image
<% end_if %>
<% if ButtonID %>
<% include BlockButton %>
<% end_if %>
按钮
TODO
页面
所有块内容都渲染到页面的内容字段中。这是为了在不调整的情况下保持搜索功能。
每个块代表一个部分,类似于这样
<section id="MyHTMLID" class="Block Block-MyBlock">
Here is the block content based on your template
</section>
如果您有更定制化的需求,可以通过禁用 wrap 块配置来禁用此自动“部分”功能
LeKoala\Blocks\BlocksPage:
wrap_blocks: false
额外数据
由于块类型不是 DataObjects,因此它们的方法没有暴露给模板,只有它们的数据
基本上,我们取所有数据字段,所有设置,并在调用“renderWith”函数之前将它们合并在一起
您可以通过使用 ExtraData 向模板公开额外的数据
function ExtraData() {
return [
'Hello' => 'World
];
}
然后在您的模板中调用
Hello $Hello
类型转换
如果您在块中存储 html,则它不会被正确转换。因此,请确保在您的模板中使用 .RAW
$Description.RAW
预览块
每次更改块以刷新页面的 $Content 变量时,都需要保存和发布,这可能有些繁琐。这就是为什么在 Dev 模式下,您可以在显示页面时将 ?live=1 作为 URL 参数传递,以完全刷新所有块内容
上下文
请记住,块的 html 在管理员中保存时生成。这意味着某些上下文信息(会话、Controller::curr)可能不会像您想象的那样工作。尽量使状态尽可能无状态,以避免惊喜!
使用查询
块为您提供了强大的访问器:$Query 方法。在您的模板中,您可以遍历任何 DATAOBJECT。请对此非常小心。
<% loop Query(TeamMembers) %>
$Name
<% end_loop %>
TODO
- 最终提取特定表单字段组件
- 去除与基础模块的耦合
兼容性
已测试与 4.6 版本兼容,但应在任何 ^4 项目中工作
维护者
LeKoala - thomas@lekoala.be