dynamedia / wn-posts-plugin
文章发布插件
Requires
- php: >=7.2
- composer/installers: ~1.0
- spatie/schema-org: ^3.4
- winter/wn-pages-plugin: ^2.0
- winter/wn-translate-plugin: ^2.0
README
此插件提供编写文章(博客文章、新闻文章等)的功能。为此,您需要包含相关插件组件的几个CMS页面。
为了正确地将此插件集成到您的网站中,您可能希望能够显示文章的内容,并有一种方式可以根据不同的标准列出文章,例如按发布日期或相关类别、标签或作者。
可在https://github.com/Dynamedia/wn-posts-demo-theme找到演示主题,这对于想要快速开始的开发者来说是一个有用的资源。此外,还可以访问https://playground.posts-plugin.dynamedia.uk上的实时和交互式演示站点。
安装后
后端用户将创建一个“个人资料”,其中可以输入额外信息。每个用户都将生成一个可配置的用户名,该用户名在前端使用,以避免暴露登录名。
配置
大多数插件配置都可以在“Dynamedia文章设置”部分的“后端设置”区域找到。一些设置是绝对的,而其他设置允许您定义一个默认值,该默认值将被文章或文章组(类别、标签)继承或覆盖。
发布者选项卡
这些设置旨在帮助搜索引擎优化,并且对于插件与主题一起生成正确的输出是必需的。
-
发布者名称 - 应包含发布内容的组织或个人的名称,例如Dynamedia Limited。
-
发布者类型 - 下拉菜单用于选择个人或组织。
-
发布者URL - 发布者的URL。这可能与当前网站URL相同或不同。
-
发布者标志 - 发布者的标志。
文章选项卡
本节用于配置用于显示文章内容的CMS页面。
-
文章显示页面(带类别) - 选择包含displayPost组件的CMS页面。建议选择同时附加displayCategory组件的页面,尽管如果您更喜欢/categories & /posts URL结构,则这不是必需的。
-
文章显示页面(无类别) - 当不遵循上述建议时,选择包含displayPost组件的CMS页面。您可以选择一个单独的CMS页面来显示未分类的文章,但建议不要这样做。
有关更多信息,请参阅本文档的组件部分。
类别选项卡
本节用于配置用于显示类别内容和相关文章列表的CMS页面。
-
类别显示页面 - 选择包含displayCategory组件的CMS页面。如上所述,建议在同一CMS页面中利用displayPost和displayCategory组件。
-
默认文章排序顺序 - 选择类别中文章的默认排序顺序。此值可以在每个单独类别的设置部分中覆盖。
-
从子类别列表文章 - 选择是否将此类别的文章列表包含子类别的文章。此值可以在每个单独类别的设置部分中覆盖。
-
每页帖子数 - 用于选择每页应显示多少篇帖子。此值可以在每个类别设置部分中覆盖。此下拉菜单的值来自 config/config.php。
标签选项卡
本节用于配置用于显示标签内容和相关帖子列表的CMS页面。
-
默认帖子排序顺序 - 定义类别中帖子的默认排序顺序。此值可以在每个类别设置部分中覆盖。
-
每页帖子数 - 用于选择每页应显示多少篇帖子。此值可以在每个类别设置部分中覆盖。此下拉菜单的值来自 config/config.php。
用户选项卡
本节用于配置用于显示用户资料和相关帖子列表的CMS页面。
-
默认帖子排序顺序 - 定义用户帖子的默认排序顺序。此值可以在每个类别设置部分中覆盖。
-
每页帖子数 - 用于选择每页应显示多少篇帖子。此下拉菜单的值来自 config/config.php。
CMS布局选项卡
插件允许动态更改主题布局,因此您不仅限于每个CMS页面(帖子、类别、标签)的单个布局文件。这为设计主题提供了很大的灵活性。一个示例用例是当设计一个涵盖多个不同主题的大型网站时。您可能希望不同部分有不同的外观。当然,本节中可用的选项将完全取决于主题中提供的布局数量。
-
默认帖子布局 - 对于未指定单独布局的类别或帖子,这是默认值。帖子可以指定布局文件,也可以从其主要类别继承。
-
默认类别布局 - 对于未指定单独布局的类别,这是默认值。
-
默认标签布局 - 对于未指定单独布局的标签,这是默认值。
组件
插件提供了一些组件。
displayPost
此组件用于显示帖子的内容。该组件没有可配置的选项,应存在于包含两个可用URL参数之一的CMS页面中。
这两个可用参数最终都会从帖子别名获取帖子,但提供了几个参数以帮助定义理想的URL结构。
:postsPostSlug 仅表示别名,例如 /my-post
:postsFullPath* 表示类别和帖子,例如 /a-category/a-subcategory/my-post,尽管当与displayCategory组件一起使用时,它也可以匹配类别别名或没有类别的帖子。
以下代码片段演示了如何实现此组件,独立于包含完整类别路径的CMS页面。
title = "Posts Page"
url = "/posts/:postsCategoryPath*/:postsPostSlug"
[displayPost]
==
{% component 'displayPost' %}
如果您想实现而不显示类别,可以这样做
title = "Posts Page Without Category"
url = "/posts/:postsPostSlug"
[displayPost]
==
{% component 'displayPost' %}
displayPost将注入以下变量
-
post - 帖子对象
-
paginator - 用于多页帖子的LengthAwarePaginator
displayCategory
此组件用于显示类别及其相关帖子列表的内容。该组件没有可配置的选项,应存在于包含两个可用URL参数之一的CMS页面中。
:postsCategorySlug 表示类别别名。
:postsCategoryPath* 表示路径中的类别部分,例如。/a-category 或 /a-category/a-sub-category
:postsFullPath* 表示类别和帖子,例如 /a-category/a-subcategory/my-post,尽管当与displayCategory组件一起使用时,它也可以匹配类别别名或没有类别的帖子。
以下代码片段演示了如何实现此组件,独立于包含完整类别路径的CMS页面。
title = "Category Display Page"
url = "/posts/category/:postsCategoryPath*"
[displayCategory]
includeSubcategories = 1
postsPerPage = 10
==
{% component 'displayCategory' %}
或者只是类别别名,但没有完整路径
title = "Category Display Page"
url = "/posts/category/:postsCategorySlug"
[displayCategory]
includeSubcategories = 1
postsPerPage = 10
==
{% component 'displayCategory' %}
displayCategory将注入以下变量
-
category - 类别对象。
-
posts - 包含帖子项的LengthAwarePaginator。
结合使用displayPost和displayCategory
建议使用相同的URL为帖子显示页面和类别显示页面。插件处理逻辑以解决URL冲突时正确解析页面。这允许使用语义URL,甚至可以从项目根开始。
您可以通过使用:postsFullPath*参数在URL中实现这一点
在这种情况下,您可以同时使用以下代码片段。
帖子显示页面。
title = "Post Display Page"
url = "/:postsFullPath*"
layout = "default"
meta_title = "Post Display Page"
is_hidden = 0
[displayPost]
==
{% component 'displayPost' %}
分类显示页面
title = "Category Display Page"
url = "/:postsFullPath*"
layout = "default"
meta_title = "Category Display Page"
is_hidden = 0
[displayCategory]
includeSubcategories = 1
postsPerPage = 11
noPostsMessage = "No posts found"
sortOrder = "published_at desc"
==
{% component 'displayCategory' %}
例如,这将匹配以下网址
https://example.org/my-uncategorized-post
https://example.org/a-category
https://example.org/a-category/my-categorized-post
然而,它不会匹配
https://example.org/my-static-page
当然,您无需从URL根开始实现,您也可以轻松地使用 url = '/posts/:postsFullPath*\'
注意:URL
上述组件都用于URL生成。当您创建了自己的首选结构并在插件设置中选择了相关页面时,帖子对象和分类对象将具有可用的url属性。您可以在{{ post.url }}和{{ category.url }}处访问这些属性。
如果您的分类结构发生变化,用户将始终被重定向到正确的URL。
例如,如果您有一个slug为'my-interesting-post'的帖子,并且它没有分类,其URL可能是https://example.org/posts/my-interesting-post
您以后可以添加一个名为'my-stuff'的分类,并选择添加帖子,这样它的URL现在变为https://example.org/posts/my-stuff/my-interesting-post
在这种情况下,https://example.org/posts/my-interesting-post将重定向到https://example.org/posts/my-stuff/my-interesting-post。
displayTag
此组件用于显示标签的内容及其关联的帖子列表。该组件没有可配置的选项。
标签将使用:postsTagSlug URL参数进行识别。
示例实现
title = "Tags"
url = "/tags/:postsTagSlug"
[displayTag]
postsPerPage = 10
==
{% component 'displayTag' %}
displayCategory将注入以下变量
-
tag - 标签对象。
-
posts - 包含帖子项的LengthAwarePaginator。
displayUser
此组件负责显示用户资料和用户的帖子。
将使用:postsUsername URL参数识别用户。
请注意,用户名不是后端登录名。用户名将由每个用户的Profile模型生成,但在用户管理设置中可以更改。
示例实现
title = "User Posts"
url = "/user/:postsUsername"
[displayUser]
==
{% component 'displayUser' %}
displayCategory将注入以下变量
-
user - 后端用户对象。
-
posts - 包含帖子项的LengthAwarePaginator。
searchPosts
此组件负责显示帖子的搜索结果。
应使用q URL参数传递搜索查询,例如
https://example.org/search?q=keyword
此组件需要一些配置
-
postsLimit - 可获取的帖子总数。
-
postsPerPage - 当此值大于postsLimit或未设置postsLimit时,结果将分页。
-
sortOrder - 下拉菜单,用于选择结果的返回顺序。
示例实现
title = "Search"
url = "/search"
[searchPosts]
postsPerPage = 10
==
{% component 'searchPosts' %}
searchPosts将注入以下变量
-
searchQuery - 搜索字符串。
-
posts - 包含帖子项的LengthAwarePaginator。
listPosts
此组件负责显示自定义帖子列表。
此组件需要一些配置
-
categoryFilter - 从所选分类获取的帖子。
-
includeSubcategories - 包含所选分类的子分类中的帖子。
-
tagFilter - 标记为所选标签的帖子。
-
postIds - 仅返回具有给定ID的帖子,按指定顺序。
-
notPostIds - 排除具有给定ID的帖子。
-
notCategoryIds - 排除具有给定ID的分类中的帖子。
-
notTagIds - 排除具有与给定ID匹配的标签的帖子。
-
postsLimit - 可获取的帖子总数。
-
postsPerPage - 当此值大于postsLimit或未设置postsLimit时,结果将分页。
-
sortOrder - 选择结果的返回顺序。
示例实现,可能适用于网站首页
title = "Home"
url = "/"
[listPosts featuredPosts]
postIds = "1,2"
postsLimit = 2
postsPerPage = 2
sortOrder = "published_at desc"
[listPosts latestPosts]
notPostIds = "1,2"
notCategoryIds = 4
notTagIds = 1
postsLimit = 5
postsPerPage = 5
sortOrder = "published_at desc"
==
<div class="content">
<div class="row">
<div class="col-12">
<h2 class="mt-4 mb-4">Featured Posts</h2>
{% component 'featuredPosts' %}
<h2 class="mt-4 mb-4">Latest posts</h2>
{% component 'latestPosts' %}
</div>
</div>
</div>
listPosts将注入以下变量
- posts - 包含帖子项的LengthAwarePaginator。
对象结构
以下部分描述了由Posts插件生成的对象中可用的属性
帖子
模型 Dynamedia\Posts\Post
表 dynamedia_posts_posts
帖子属性
*附加属性
为了帮助开发,以下提供了一些示例dd转储,用于数组属性。
body属性
^ array:4 [▼
0 => array:2 [▼
"block" => array:5 [▼
"sId" => "first"
"image" => array:4 [▼
"alt" => ""
"class" => ""
"default" => ""
"image_style" => "inline-left"
]
"content" => "<p>Construct your posts using as many or as few blocks as you like!</p><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incidid ▶"
"heading" => "A content block"
"in_contents" => "1"
]
"_group" => "section"
]
1 => array:2 [▶]
2 => array:1 [▼
"_group" => "pagebreak"
]
3 => array:2 [▼
"block" => array:5 [▼
"sId" => "third"
"image" => array:4 [▶]
"content" => "<p>Posts can, if you want, be written over multiple pages. It's all handled internally so just add a pagebreak block. Easy!</p>"
"heading" => "New page content"
"in_contents" => "1"
]
"_group" => "section"
]
]
pages属性
这是从body派生出来的,通过分页符分隔body部分
^ array:2 [▼
0 => array:2 [▼
0 => array:3 [▼
"block" => array:5 [▼
"sId" => "first"
"image" => array:4 [▶]
"content" => "<p>Construct your posts using as many or as few blocks as you like!</p><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incidid ▶"
"heading" => "A content block"
"in_contents" => "1"
]
"_group" => "section"
"page" => 1
]
1 => array:3 [▶]
]
1 => array:1 [▼
0 => array:3 [▼
"block" => array:5 [▼
"sId" => "third"
"image" => array:4 [▶]
"content" => "<p>Posts can, if you want, be written over multiple pages. It's all handled internally so just add a pagebreak block. Easy!</p>"
"heading" => "New page content"
"in_contents" => "1"
]
"_group" => "section"
"page" => 2
]
]
]
images属性
这部分包含主图像,这些图像与帖子正文中的图像分开。应使用 | media twig 过滤器来使用 URL。
^ array:3 [▼
"list" => array:3 [▼
"alt" => "The List Image"
"class" => "optional-class"
"default" => "/list-image.png"
]
"banner" => array:3 [▼
"alt" => "The Banner Image"
"class" => "optional-class"
"default" => "/banner-image.png"
]
"social" => array:2 [▼
"twitter" => "/twitter-image.png"
"facebook" => "/facebook-image.png"
]
]
contents_list 属性
在_contents 设置为 true 的帖子部分
^ array:3 [▼
0 => array:4 [▼
"title" => "A content block"
"page" => 1
"url" => "http://octobercms.local/uncategorized/first-blog-post#first"
0 => "contents_list"
]
1 => array:4 [▼
"title" => "Another content block"
"page" => 1
"url" => "http://octobercms.local/uncategorized/first-blog-post#second"
0 => "contents_list"
]
2 => array:4 [▼
"title" => "New page content"
"page" => 2
"url" => "http://octobercms.local/uncategorized/first-blog-post?page=2#third"
0 => "contents_list"
]
]
帖子关系
类别
模型 Dynamedia\Posts\Category
表 dynamedia_posts_categories
类别属性
*附加属性
类别关系
标签
模型 Dynamedia\Posts\Tag
表 dynamedia_posts_tags
标签属性
*附加属性
标签关系
个人资料
模型 Dynamedia\Posts\Profile
表 dynamedia_posts_profiles
个人资料属性
*附加属性
个人资料关系
注意:此文档将定期更新和改进。有关更多信息,请参阅 https://posts-plugin.dynamedia.uk。