# CMS主题教程
# Cms主题模块开发步骤
# 第一步、准备工作
# 1.1) 准备静态HTML模板
准备需要开发的静态资源模板文件,结构可参考如下
└─ template/ → 模板根目录
└─ static/ → 静态资源
├─ css/
│ ├── style.css
│ └── ......
├─ js/
│ ├── script.js
│ └── ......
├─ image/
│ ├── image.jpg
│ └── ......
├─ listDefault.html → 默认列表
├─ listNews.html → 新闻列表
├─ listProduct.html → 产品列表
├─ listCase.html → 案例列表
├─ detailDefault.html → 默认详情
├─ detailNews.html → 新闻详情
├─ detailProduct.html → 产品详情
├─ detailCase.html → 案例详情
└─ index.html → 首页
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 1.2) 安装模块开发助手
模块开发助手可以极大效率的提高开发效率,在 系统管理 → 模块管理
安装 模块开发助手 (opens new window) 。
# 第二步、模块开发
# 2.1) 创建模块
访问 系统管理 → 模块开发助手
,通过常用工具创建模块
# 2.2) 安装启用主题模块
访问 系统管理 → 模块管理 → 本地模块
,安装并启用模块。
# 2.3) 主题模块开发完成
以下教程以主题模块 CmsThemeMyTest
为例进行。
2.3.1) 复制静态资源
复制静态HTML模板中的所有静态资源文件 template/static/
到主题模块静态资源 module/CmsThemeMyTest/Asset
中。
如,静态HTML模板结构为
└─ template/ → 模板根目录
└─ static/
├─ css
│ └─ style.css
├─ js
│ └─ script.js
└─ image
└─ image.jpg
2
3
4
5
6
7
8
复制到模块静态资源结构为
└─ module/CmsThemeMyTest/Asset/ → 模块静态资源结构
└─ static/
├─ css
│ └─ style.css
├─ js
│ └─ script.js
└─ image
└─ image.jpg
2
3
4
5
6
7
8
2.3.2) 做静态资源软连
开发阶段为了模块开发方便,访问的静态资源使用软连链接到模块静态资源文件夹。先删除 public/vendor/CmsThemeMyTest/ 目录,然后执行以下命令完成软连创建。
php artisan modstart:module-link-asset CmsThemeMyTest
这样,访问路径 http://example.com/vendor/CmsThemeMyTest/css/style.css
路径会定向到文件 module/CmsThemeMyTest/Asset/css/style.css
。
2.3.3) 完成模板开发
复制以下页面到模块,并完成页面功能开发。
- 列表页:
listDefault.html
→module/CmsThemeMyTest/View/pc/cms/list/default.blade.php
- 列表页:
listNews.html
→module/CmsThemeMyTest/View/pc/cms/list/news.blade.php
- 列表页:
listProduct.html
→module/CmsThemeMyTest/View/pc/cms/list/product.blade.php
- 列表页:
listCase.html
→module/CmsThemeMyTest/View/pc/cms/list/case.blade.php
- 详情页:
detailDefault.html
→module/CmsThemeMyTest/View/pc/cms/detail/default.blade.php
- 详情页:
detailNews.html
→module/CmsThemeMyTest/View/pc/cms/detail/news.blade.php
- 详情页:
detailProduct.html
→module/CmsThemeMyTest/View/pc/cms/detail/product.blade.php
- 详情页:
detailCase.html
→module/CmsThemeMyTest/View/pc/cms/detail/case.blade.php
- 首页:
index.html
→module/CmsThemeMyTest/View/pc/cms/index.blade.php
要面开发主要需要以下两个步骤:
① 完成页面所有静态资源的路径替换
将所有路径 path/to/static 替换为 @asset('vendor/CmsThemeMyTest/path/to/static')
script
<script src="static/js/script.js"></script>
替换为
<script src="@asset('vendor/CmsThemeMyTest/static/js/script.js')"></script>
css
<link rel="stylesheet" href="static/css/style.css">
替换为
<link rel="stylesheet" href="@asset('vendor/CmsThemeMyTest/static/css/style.css')">
图片
<img src="static/image/image.jpg" />
替换为
<img src="@asset('vendor/CmsThemeMyTest/static/image/image.jpg')" />
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
② 完成页面变量替换和内容渲染
该部分每个页面需要参考个页面可用变量完成开发和内容替换。
更多的主题模块的开发可以参照 CmsThemeDemo (opens new window),该示例中涵盖了主题模块开发的示例。
# 第三步、模块发布分享
# 3.1) 账户信息认证
- 注册ModStart账号:访问 https://modstart.com (opens new window) 完成账号注册
- 实名认证:在用户中心完成用户实名认证
# 3.2) 在平台创建信息模块
在 个人中心 → 开发者 → 开发者中心
创建模块,填写基础模块信息完成创建。
# 3.3) 模块打包上传到模块市场
进入 系统管理 → 模块开发助手
,使用相同的 ModStart 账号登录,对于拥有的模块操作栏会出现发布按钮,点击发布一键发布到模块市场。
发布成功后,需要后台审核模块,完成审核后模块即可显示在模块市场。
# 模块文件介绍
# 目录结构
module/CmsThemeXxx
├─ Admin/ → 后台管理
│ ├─ Controller/
│ │ └─ ConfigController.php → 后台配置开发Controller
│ └─ routes.php → 路由
├─ Asset/ → 模块资源文件,安装后会复制到 public/vendor/CmsThemeXxx
│ └─ ......
├─ Core/
│ ├─ CmsThemeProvider.php → CMS主题注册器
│ ├─ ModuleServiceProvider.php → 模块核心注册器
│ └─ ThemeSiteTemplateProvider.php → 主题注册器,用于注册当前模块为博客主题
├─ Docs/ → 模块文档
│ ├─ module/
│ │ ├─ content.md → 模块介绍,发布时自动更新到模块介绍
│ │ ├─ demo.md → 模块演示,发布时自动更新到模块演示
│ │ ├─ mobilePreview.md → 模块手机预览图,每行一个支持多个,发布时自动更新
│ │ └─ preview.md → 模块电脑端预览图,每行一个支持多个,发布时自动更新
│ └─ release.md → 模块发布日志,发布时自动更新到模块发布日志
├─ Lang/ → 多语言
│ ├─ en.php → 英文语言包
│ └─ zh.php → 中文语言包
├─ View/ → 模块视图主目录
│ └─ pc/ → 电脑端视图
│ ├─ cms/ → CMS视图
│ │ ├─ detail/ → 详情视图
│ │ │ ├─ default.blade.php
│ │ │ └─ ......
│ │ ├─ form/ → 表单视图
│ │ │ └─ default.blade.php
│ │ ├─ list/ → 列表视图
│ │ │ ├─ default.blade.php
│ │ │ └─ ......
│ │ ├─ page/ → 单页视图
│ │ │ └─ default.blade.php
│ │ └─ index.blade.php → 首页
│ ├─ footer.blade.php → 公共视图底部
│ ├─ frame.blade.php → 公共视图框架
│ ├─ frameTheme.blade.php → 主题视图框架
│ └─ header.blade.php → 公共视图顶部
└─ config.json → 模块配置文件
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# CMS链接
/tag/{name}
标签列表/a/{id}
内容页面/search?keywords={keywords}
搜索列表
除了以上默认的地址方式外,所有页面都需要在后台栏目中自定义。
# CMS首页 cms.index
首页暂无系统变量,所有页面部分均需自定调用。
# 列表页面 cms.list.default
# 内容记录 $records
循环输入内容列表
@foreach($records as $record)
<a href="{{$record['_url']}}">{{$record['title']}}</a>
@endforeach
2
3
变量 | 说明 |
---|---|
$records | 记录数组 |
├ $record['id'] | 内容ID |
├ $record['created_at'] | 创建时间 |
├ $record['updated_at'] | 更新时间 |
├ $record['catId'] | 栏目ID |
├ $record['modelId'] | 模型ID |
├ $record['title'] | 标题 |
├ $record['summary'] | 摘要 |
├ $record['cover'] | 封面 |
├ $record['postTime'] | 发布时间 |
├ $record['wordCount'] | 字数 |
├ $record['viewCount'] | 浏览次数 |
├ $record['commentCount'] | 评论数 |
├ $record['likeCount'] | 喜欢数 |
├ $record['isRecommend'] | 是否推荐 |
├ $record['isTop'] | 是否置顶 |
├ $record['tags'] | 标签 |
├ $record['_tags'] | 标签数组 ['标签1', ...] |
├ $record['_tagList] | 标签数组 [ {'name':'标签1','url':'标签2'}, ...] |
├ $record['author'] | 作者 |
├ $record['source'] | 来源 |
├ $record['seoTitle'] | SEO标题 |
├ $record['seoDescription'] | SEO描述 |
├ $record['seoKeywords'] | SEO关键词 |
├ $record['_url'] | 内容URL |
├ $record['_day'] | 内容发布日期 |
└ $record['_data']['xxx'] | 自定义字段 |
# 当前栏目 $cat
变量 | 说明 |
---|---|
$cat['id'] | 栏目ID |
$cat['pid'] | 父级栏目ID |
$cat['title'] | 栏目标题 |
$cat['url'] | 栏目URL |
$cat['modelId'] | 栏目模型ID |
$cat['seoTitle'] | SEO标题 |
$cat['seoDescription'] | SEO描述 |
$cat['seoKeywords'] | SEO关键词 |
$cat['icon'] | 栏目图标 |
$cat['cover'] | 栏目封面 |
$cat['subTitle'] | 栏目子标题 |
$cat['bannerBg'] | 栏目Banner背景 |
$cat['_model'] | 栏目模型 |
$cat['_model']['title'] | 栏目模型名称 |
$cat['_model']['name'] | 栏目模型标识 |
# 顶级栏目 $catRoot
如果当前栏目为顶级栏目,则该变量与 $cat
相同。
变量 | 说明 |
---|---|
$cat['id'] | 栏目ID |
$cat['pid'] | 父级栏目ID |
$cat['title'] | 栏目标题 |
$cat['url'] | 栏目URL |
$cat['modelId'] | 栏目模型ID |
$cat['seoTitle'] | SEO标题 |
$cat['seoDescription'] | SEO描述 |
$cat['seoKeywords'] | SEO关键词 |
$cat['icon'] | 栏目图标 |
$cat['cover'] | 栏目封面 |
$cat['subTitle'] | 栏目子标题 |
$cat['bannerBg'] | 栏目Banner背景 |
$cat['_model'] | 栏目模型 |
$cat['_model']['title'] | 栏目模型名称 |
$cat['_model']['name'] | 栏目模型标识 |
# 子栏目 $catChildren
@foreach ($catChildren as $cat)
<a href="{{$cat['_url']}}">{{$cat['title']}}</a>
@endforeach
2
3
变量 | 说明 |
---|---|
$cats | 记录数组 |
├ $cat['id'] | 栏目ID |
├ $cat['pid'] | 父级栏目ID |
├ $cat['title'] | 栏目标题 |
├ $cat['url'] | 栏目URL |
├ $cat['modelId'] | 栏目模型ID |
├ $cat['seoTitle'] | SEO标题 |
├ $cat['seoDescription'] | SEO描述 |
├ $cat['seoKeywords'] | SEO关键词 |
├ $cat['icon'] | 栏目图标 |
├ $cat['cover'] | 栏目封面 |
├ $cat['subTitle'] | 栏目子标题 |
├ $cat['bannerBg'] | 栏目Banner背景 |
├ $cat['_model'] | 栏目模型 |
├ $cat['_model']['title'] | 栏目模型名称 |
└ $cat['_model']['name'] | 栏目模型标识 |
# 顶级栏目子栏目 $catRootChildren
@foreach ($catRootChildren as $cat)
<a href="{{$cat['_url']}}">{{$cat['title']}}</a>
@endforeach
2
3
变量 | 说明 |
---|---|
$cats | 记录数组 |
├ $cat['id'] | 栏目ID |
├ $cat['pid'] | 父级栏目ID |
├ $cat['title'] | 栏目标题 |
├ $cat['url'] | 栏目URL |
├ $cat['modelId'] | 栏目模型ID |
├ $cat['seoTitle'] | SEO标题 |
├ $cat['seoDescription'] | SEO描述 |
├ $cat['seoKeywords'] | SEO关键词 |
├ $cat['icon'] | 栏目图标 |
├ $cat['cover'] | 栏目封面 |
├ $cat['subTitle'] | 栏目子标题 |
├ $cat['bannerBg'] | 栏目Banner背景 |
├ $cat['_model'] | 栏目模型 |
├ $cat['_model']['title'] | 栏目模型名称 |
└ $cat['_model']['name'] | 栏目模型标识 |
# 栏目面包屑 $catChain
@foreach ($catChain as $cat)
<a href="{{$cat['_url']}}">{{$cat['title']}}</a>
@endforeach
2
3
变量 | 说明 |
---|---|
$cats | 记录数组 |
├ $cat['id'] | 栏目ID |
├ $cat['pid'] | 父级栏目ID |
├ $cat['title'] | 栏目标题 |
├ $cat['url'] | 栏目URL |
├ $cat['modelId'] | 栏目模型ID |
├ $cat['seoTitle'] | SEO标题 |
├ $cat['seoDescription'] | SEO描述 |
├ $cat['seoKeywords'] | SEO关键词 |
├ $cat['icon'] | 栏目图标 |
├ $cat['cover'] | 栏目封面 |
├ $cat['subTitle'] | 栏目子标题 |
├ $cat['bannerBg'] | 栏目Banner背景 |
├ $cat['_model'] | 栏目模型 |
├ $cat['_model']['title'] | 栏目模型名称 |
└ $cat['_model']['name'] | 栏目模型标识 |
# 分页 $page
$pageSize
$pageHtml
# 当前页数 $page
{{$page}}
# 分页大小 $pageSize
{{$pageSize}}
# 分页HTML
$pageHtml
{!! $pageHtml !!}
当前列表分页HTML数据
<div class="pages">
<a href="?page=1">1</a>
<span>2</span>
<a href="?page=1">3</a>
</div>
2
3
4
5
6
如果使用系统完整分页条,则以上样式名称在输出的HTML代码中都带,可以直接使用对应名称在自己的css中定义具体样式即可。
# 自定义分页
{!! \ModStart\Core\Util\PageHtmlUtil::render($total, $pageSize, $page,
'?' . \ModStart\Core\Input\Request::mergeQueries(['page' => ['{page}']]), [
'warp' => '<div>%s%</div>',
'more' => '<span>...</span>',
'prev' => '<a href="%s%">上一页</a>',
'prevDisabled' => '<span>上一页</span>',
'next' => '<a href="%s%">下一页</a>',
'nextDisabled' => '<span>下一页</span>',
'first' => '<a href="%s%">首页</a>',
'last' => '<a href="%s%">尾页</a>',
'current' => '<span>%p%</span>',
'item' => '<a href="%s%">%p%</a>',
]) !!}
2
3
4
5
6
7
8
9
10
11
12
13
# 下一页链接 $pageNextUrl
{{$pageNextUrl}}
# 上一页链接 $pagePrevUrl
{{$pagePrevUrl}}
# 列表条件过滤
如果需要进行自定义字段的筛选,需要设置字段以下属性
- 字段开启「列表搜索」
- 字段开启「访客列表页面可见」
随后在URL中传递该参数即可实现列表页面的条件过滤。
# 详情页面 cms.detail.default
# 内容详情 $record
标题:{{ $record['title'] }}
内容:{{ $record['content'] }}
2
变量 | 说明 |
---|---|
$record['id'] | 内容ID |
$record['created_at'] | 创建时间 |
$record['updated_at'] | 更新时间 |
$record['catId'] | 栏目ID |
$record['modelId'] | 模型ID |
$record['title'] | 标题 |
$record['summary'] | 摘要 |
$record['cover'] | 封面 |
$record['postTime'] | 发布时间 |
$record['wordCount'] | 字数 |
$record['viewCount'] | 浏览次数 |
$record['commentCount'] | 评论数 |
$record['likeCount'] | 喜欢数 |
$record['isRecommend'] | 是否推荐 |
$record['isTop'] | 是否置顶 |
$record['tags'] | 标签数组 |
$record['_tags'] | 标签数组 ['标签1', ...] |
$record['_tagList] | 标签数组 [ {'name':'标签1','url':'标签2'}, ...] |
$record['author'] | 作者 |
$record['source'] | 来源 |
$record['seoTitle'] | SEO标题 |
$record['seoDescription'] | SEO描述 |
$record['seoKeywords'] | SEO关键词 |
$record['_data']['content'] | 内容 |
$record['_data']['xxx'] | 自定义字段 |
# 当前栏目 $cat
变量 | 说明 |
---|---|
$cat['id'] | 栏目ID |
$cat['pid'] | 父级栏目ID |
$cat['title'] | 栏目标题 |
$cat['url'] | 栏目URL |
$cat['modelId'] | 栏目模型ID |
$cat['seoTitle'] | SEO标题 |
$cat['seoDescription'] | SEO描述 |
$cat['seoKeywords'] | SEO关键词 |
$cat['icon'] | 栏目图标 |
$cat['cover'] | 栏目封面 |
$cat['subTitle'] | 栏目子标题 |
$cat['bannerBg'] | 栏目Banner背景 |
$cat['_model'] | 栏目模型 |
$cat['_model']['title'] | 栏目模型名称 |
$cat['_model']['name'] | 栏目模型标识 |
# 表单页面 cms.form.default
# 通用表单
提交到 modstart_api_url('cms/form/submit',['cat'=>7])
,其中 cat
为栏目ID。
需要提交的字段,提交则字段不能全部为空。
content
内容xxx
其他自定义字段
# 留言本
<form action="{{ modstart_web_url('cms/form/submit',['cat'=>7]) }}"
method="post" data-ajax-form>
手机:<input type="text" name="phone" >
姓名:<input type="text" name="name" >
内容:<input type="text" name="content" >
<button type="submit">提交</button>
</form>
需要注意,表单提交需要引入这两个JS来处理 data-ajax-form 的表单提交
<script src="@asset('asset/vendor/jquery.js')"></script>
<script src="@asset('asset/common/base.js')"></script>
2
3
4
5
6
7
8
9
10
# 标签页 cms.tag.index
# 搜索页 cms.search.index
# 通用页面
# 公共变量
$pageTitle
页面标题$pageKeywords
页面关键词$pageDescription
页面描述
# 配置
// 网站名称
{{ modstart_config('siteName') }}
// 网站Logo
{{ modstart_config_asset_url('siteLogo') }}
// 网站副标题
{{ modstart_config('siteSlogan') }}
// 网站域名
{{ modstart_config('siteDomain') }}
// 网站关键词
{{ modstart_config('siteKeywords') }}
// 网站描述
{{ modstart_config('siteDescription') }}
// 备案编号
{{ modstart_config('siteBeian') }}
// 网站ICO
{{ modstart_config_asset_url('siteFavIco') }}
// 网站主色调
{{ modstart_config('sitePrimaryColor') }}
// 网站主题
{{ modstart_config('siteTemplate') }}
// 联系方式-邮箱
{{ modstart_config('Site_ContactEmail') }}
// 联系方式-电话
{{ modstart_config('Site_ContactPhone') }}
// 联系方式-地址
{{ modstart_config('Site_ContactAddress') }}
// 联系方式-二维码
{{ modstart_config_asset_url('Site_ContactQrcode') }}
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
27
28
// 企业名称
{{ modstart_config('Cms_CompanyName') }}
// 企业传真
{{ modstart_config('Cms_ContactFax') }}
// 联系人
{{ modstart_config('Cms_ContactContactPerson') }}
// 企业联系QQ
{{ modstart_config('Cms_ContactQQ') }}
// 企业介绍标题
{{ modstart_config('Cms_HomeInfoTitle') }}
// 企业介绍图片
{{ modstart_config_asset_url('Cms_HomeInfoImage') }}
// 企业介绍说明,富文本
{!! modstart_config('Cms_HomeInfoContent') !!}
2
3
4
5
6
7
8
9
10
11
12
13
14
# 导航
# 循环显示导航
@foreach(MNav::all('head') as $nav)
<a href="{{ $nav['link'] }}">{{ $nav['name'] }}</a>
@endforeach
2
3
变量 | 说明 |
---|---|
$nav['name'] | 导航名称 |
$nav['link'] | 导航链接 |
$nav['_child'] | 子导航(空表示只有一级导航,不为空表示为二级导航) |
$nav['openType'] | 打开方式(2=新窗口 其他值=当前窗口) |
# 不同的位置
MNav::all('head'); // 头部导航
MNav::all('foot'); // 底部导航
2
# 多级嵌套(最多支持三级菜单)
@foreach(MNav::all('head') as $nav)
@if(empty($nav['_child']))
<!-- 无二级导航 -->
<a href="{{ $nav['link'] }}">{{ $nav['name'] }}</a>
@else
<!-- 有二级导航 -->
<div class="title">
<a href="{{$nav['link']}}">{{$nav['name']}}</a>
</div>
<div class="child">
@foreach($nav['_child'] as $nav2)
@if(empty($nav2['_child']))
<!-- 无三级导航 -->
<a href="{{$nav2['link']}}">{{$nav2['name']}}</a>
@else
<!-- 有三级导航 -->
<div class="title">
<a href="{{$nav2['link']}}">{{$nav2['name']}}</a>
</div>
<div class="child">
@foreach($nav2['_child'] as $nav3)
<a href="{{$nav3['link']}}">{{$nav3['name']}}</a>
@endforeach
</div>
@endif
@endforeach
</div>
@endif
@endforeach
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
27
28
29
# 高亮菜单
当前URL匹配链接时输出 CSS 类 active
@foreach(MNav::all('head') as $nav)
<a href="{{ $nav['link'] }}"
class="{{modstart_baseurl_active($nav['link'],'active')}}">
{{ $nav['name'] }}
</a>
@endforeach
2
3
4
5
6
更多参考 Nav (opens new window) 模块
# 轮播
# 循环显示轮播
// 循环特定位置轮播
@foreach(MBanner::all('Xxx') as $banner)
@if($banner['type']===\Module\Banner\Type\BannerType::IMAGE)
图片
<a href="{{ $banner['link'] }}">{{ $banner['image'] }}</a>
@elseif($banner['type']===\Module\Banner\Type\BannerType::IMAGE_TITLE_SLOGAN_LINK)
图片+标题+描述+链接
<a href="{{ $banner['link'] }}">{{ $banner['image'] }}</a>
<span>{{ $banner['title'] }}</span>
<span>{{ $banner['slogan'] }}</span>
<a href="{{ $banner['link'] }}">{{ $banner['linkText'] }}</span>
@elseif($banner['type']===\Module\Banner\Type\BannerType::VIDEO)
视频
<a href="{{ $banner['link'] }}">{{ $banner['video'] }}</a>
@endif
@endforeach
// 循环特定位置轮播(仅包含图片)
@foreach(MBanner::allImage('Xxx') as $banner)
<a href="{{ $banner['link'] }}">{{ $banner['image'] }}</a>
@endforeach
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 支持多个位置
// 位置 Blog
\MBanner::all('Blog')
// 位置 Cms
\MBanner::all('Cms')
2
3
4
更多使用可参考 Banner (opens new window) 模块
# 友情链接
# 循环显示友情链接
// 循环特定位置友情链接
@foreach(\MPartner::all('Xxx') as $partner)
<a href="{{ $partner['link'] }}">{{ $partner['title'] }}</a>
@endforeach
2
3
4
# 不同位置友情链接
// 位置 Blog
\MPartner::all('Blog')
// 位置 Cms
\MPartner::all('Cms')
2
3
4
更多使用可参考 Partner (opens new window) 模块
# 站点地图
启用网站需要安装 SiteMapManager (opens new window) 模块获得支持,设置后访问路径如下:
- `http://www.example.com/sitemap.xml`
系统使用动态站点地图,不需要手动生成,访问地址即为实时地图,输出格式为xml格式。具体使用方式可参考 SiteMapManager (opens new window) 模块的使用方法。
# 用户
@if(\Module\Member\Auth\MemberUser::isLogin())
用户ID:{{$_memberUser['id']}}
用户名:{{$_memberUser['username']}}
昵称:{{$_memberUser['nickname']}}
@else
请登录
@endif
2
3
4
5
6
7
变量 | 说明 |
---|---|
$_memberUserId | 用户ID,可以判断该变量是否为空来判断用户是否登录 |
$_memberUser['id'] | 用户ID |
$_memberUser['username'] | 用户名 |
$_memberUser['avatar'] | 头像 |
$_memberUser['nickname'] | 昵称 |
# 内容区块
# 获取一个区块内容
@foreach([MContentBlock::getCached('标识')] as $cb)
@if(!empty($cb))
<p>类型:{{$cb['type']}}</p>
<p>名称:{{$cb['name']}}</p>
<p>备注:{{$cb['remark']}}</p>
<p>通用</p>
<p>图片:{{join(',',$cb['texts'])}}</p>
<p>图片:{{join(',',$cb['basicImages'])}}</p>
<p>图片</p>
<p>图片:{{$cb['image']}}</p>
<p>富文本</p>
<p>HTML:{{$cb['content']}}</p>
@endif
@endforeach
2
3
4
5
6
7
8
9
10
11
12
13
14
# 获取多个区块内容
@foreach(MContentBlock::allCached('标识',5) as $cb)
<p>类型:{{$cb['type']}}</p>
<p>名称:{{$cb['name']}}</p>
<p>备注:{{$cb['remark']}}</p>
<p>通用</p>
<p>图片:{{join(',',$cb['texts'])}}</p>
<p>图片:{{join(',',$cb['basicImages'])}}</p>
<p>图片</p>
<p>图片:{{$cb['image']}}</p>
<p>富文本</p>
<p>HTML:{{$cb['content']}}</p>
@endforeach
2
3
4
5
6
7
8
9
10
11
12
# 指定内容
// 根据ID获取内容
<?php $record = MCms::getContent(1); ?>
2
标题:{{ $record['title'] }}
内容:{{ $record['content'] }}
2
变量 | 说明 |
---|---|
$record['id'] | 内容ID |
$record['created_at'] | 创建时间 |
$record['updated_at'] | 更新时间 |
$record['catId'] | 栏目ID |
$record['modelId'] | 模型ID |
$record['title'] | 标题 |
$record['summary'] | 摘要 |
$record['cover'] | 封面 |
$record['postTime'] | 发布时间 |
$record['wordCount'] | 字数 |
$record['viewCount'] | 浏览次数 |
$record['commentCount'] | 评论数 |
$record['likeCount'] | 喜欢数 |
$record['isRecommend'] | 是否推荐 |
$record['isTop'] | 是否置顶 |
$record['tags'] | 标签数组 |
$record['_tags'] | 标签数组 ['标签1', ...] |
$record['_tagList] | 标签数组 [ {'name':'标签1','url':'标签2'}, ...] |
$record['author'] | 作者 |
$record['source'] | 来源 |
$record['seoTitle'] | SEO标题 |
$record['seoDescription'] | SEO描述 |
$record['seoKeywords'] | SEO关键词 |
$record['_data']['content'] | 内容 |
$record['_data']['xxx'] | 自定义字段 |
# 指定栏目
// 根据栏目ID获取栏目信息
<?php $cat = MCms::getCat(1); ?>
// 根据栏目URL获取栏目信息
<?php $cat = MCms::getCatByUrl('news'); ?>
2
3
4
变量 | 说明 |
---|---|
$cat['id'] | 栏目ID |
$cat['pid'] | 父级栏目ID |
$cat['title'] | 栏目标题 |
$cat['url'] | 栏目URL |
$cat['modelId'] | 栏目模型ID |
$cat['seoTitle'] | SEO标题 |
$cat['seoDescription'] | SEO描述 |
$cat['seoKeywords'] | SEO关键词 |
$cat['icon'] | 栏目图标 |
$cat['cover'] | 栏目封面 |
$cat['subTitle'] | 栏目子标题 |
$cat['bannerBg'] | 栏目Banner背景 |
$cat['_model'] | 栏目模型 |
$cat['_model']['title'] | 栏目模型名称 |
$cat['_model']['name'] | 栏目模型标识 |
留言本使用了通用模型 id = 7 的内容模型,如过手动调整过内容模型,请自行修改代码。
# 表单详情
@foreach($cat['_model']['_customFields'] as $customField)
@if($customField['fieldType']=='text')
<!-- 文本字段 -->
<div>
{{$customField['title']}}
:
<input class="form" type="text" name="{{$customField['name']}}" />
</div>
@else
<!-- 其他字段 -->
@endif
@endforeach
2
3
4
5
6
7
8
9
10
11
12
具体可参照 通用表单模板 (opens new window)
# 可用变量
变量 | 说明 |
---|---|
$customField['modelId'] | 模型ID |
$customField['title'] | 字段名 |
$customField['name'] | 字段 |
$customField['fieldType'] | 字段类型 |
$customField['fieldData'] | 字段数据 |
$customField['isRequired'] | 必填 |
$customField['placeholder'] | 输入提示 |
# 适配模块-标签云
需要安装 TagManager (opens new window) 模块。
@foreach (\Module\TagManager\Util\TagManagerUtil::allVisible('cms') as $tag)
<a href="{{ modstart_web_url('tag/'.urlencode($tag['tag'])) }}">{{ $tag['tag'] }}</a>
@endforeach
2
3
更多使用方式参考 模块使用 (opens new window)。
# 视图开发
# 网站主色调
可以通过 CSS 的变量 var(--color-primary)
获取,该变量会根据用户后台设置的主色调来动态改变。
# 页面框架与继承
通常情况下一个主题结构如图所示
├── 视图根目录 → 模块视图主目录
│ └── pc → 自适应默认为PC
│ ├── xxx → 模块视图子目录
│ │ ├── list.blade.php → 详情页
│ │ ├── show.blade.php → 列表页
│ │ ├── index.blade.php → 首页
│ ├── footer.blade.php
│ ├── frame.blade.php → 框架视图
│ └── header.blade.php
2
3
4
5
6
7
8
9
# 框架视图 frame.blade.php
通过会在模板文件中可以通过 @extends($_viewFrame)
来确定当前模板的框架视图,该文件通常包含公共的头部、尾部、侧边栏等内容。
$_viewFrame
会根据当前模板查找最先匹配到的文件,通常情况下,该变量会按照如下顺序查找:
resources/views/theme/<主题>/pc/frame.blade.php
module/<主题模块>/View/pc/frame.blade.php
resources/views/theme/default/pc/frame.blade.php
请保证 frame.blade.php
文件为以下结构,完整结构可参考 vendor/modstart/modstart/views/layout/frame.blade.php
<!doctype html>
<html>
<head>
...
<title>@section('pageTitle')@yield('pageTitleMain','') | {{modstart_config('siteName')}}@endsection</title>
<meta name="keywords" content="@yield('pageKeywords','')">
<meta name="description" content="@yield('pageDescription','')">
@section('headAppend')@show
</head>
<body>
@section('body')
@section('bodyContent')@show
@show
@section('bodyAppend')@show
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 页面视图
@extends($_viewFrame)
@section('pageTitleMain')我的视图标题@endsection
@section('bodyContent')
<div class="ub-container">
我的视图文件
</div>
@endsection
2
3
4
5
6
7
8
9
其中:
$_viewFrame
变量表示当前系统使用的框架视图@section('pageTitleMain')
为系统标题@section('bodyContent')
为系统正文内容部分
# 自适应的设备视图
根据访问设备的不同,会启用不同的视图文件,具体逻辑可参照 \ModStart\Core\View\ResponsiveViewTrait
中的逻辑。
- PC端使用
pc/
中的视图 - 手机端使用
m/
中的视图 - 当手机端视图不存在时,会自动降级使用
pc/
中的视图
# 系统路径
// 系统路径
{{ modstart_web_url('foo/bar') }}
// 系统路径,带域名
{{ modstart_web_full_url('foo/bar') }}
2
3
4
# 页面 section 修改
<!--为页面设置标题 -->
@section('pageTitle')页面标题@endsection
<!--设置页面主标题(会自动补全网站名称)-->
@section('pageTitleMain')页面主标题@endsection
<!--设置页面关键词-->
@section('pageKeywords')页面关键词@endsection
<!--设置页面描述-->
@section('pageDescription')页面描述@endsection
<!--在页面head上追加内容-->
@section('headAppend')
@parent
<script src="head.js"></script>
@endsection
<!--在页面body上追加内容-->
@section('bodyAppend')
@parent
<script src="body.js"></script>
@endsection
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 使用 @asset 引入路径
使用 @asset 指令可以引入静态资源,同时会自动添加版本号,以便于浏览器缓存。
<script src="@asset('foo/bar.js')"></script>
<link rel="stylesheet" href="@asset('vendor/Xxx/style/test.css')" />
<img src="@asset('vendor/Xxx/image/test.jpg')" />
2
3
最终显示在浏览器端的HTML代码为
<script src="/foo/bar.js?4015423772"></script>
<link rel="stylesheet" href="/vendor/Xxx/style/test.css?4015427772" />
<img src="/vendor/Xxx/image/test.jpg?4015423772" />
2
3
其中文件后加的 Hash 值在文件内容变动时会变化,避免了浏览器缓存。
# 页面 JS 和 CSS
页面 JavaScript
会自动放在页面尾部(</body>
之前)
// 引入行内 js
\ModStart\ModStart::script('console.log("Hello ModStart");');
// 引入一个 JavaScript 文件内容到页面
\ModStart\ModStart::js('文件路径.js');
// 引入一个 js 文件路径到页面
\ModStart\ModStart::js('文件路径.js');
2
3
4
5
6
页面 CSS
会自动放在头部(</head>
之前)
// 引入行内 css
\ModStart\ModStart::style('.test{ color:red; }');
// 引入一个 CSS 文件内容到页面
\ModStart\ModStart::styleFile('文件路径.css');
// 引入一个 CSS 文件路径到页面
\ModStart\ModStart::css('文件路径.css');
2
3
4
5
6
# 时间格式化
// $t = '2021-01-01 00:00:00'
date('Y-m-d', strtotime($t) )
2
时间格式化标签和PHP时间格式化语法一致,分别用不同字母代替,中间可以穿插任意字符,如:Y-m-d
、Y/m/d
、Y年m月d日
等
注意:Y代表完整年份,y代表简化年份,m代表月份,d代表日,H代表小时,i代表分,s代表秒,更多请参考PHP时间格式化语法 ,参考链接 :http://php.net/manual/zh/function.date.php (opens new window)
# HTML去除标签
// 去除HTML并限制输出 100 个字符
\ModStart\Core\Util\HtmlUtil::text($html,100)
2
一般在首页等特殊位置需要调取正文一段纯文本时使用,这时一般会配合下面的内容截取标签一起使用
# 内容截取
// HTML
\ModStart\Core\Util\HtmlUtil::text($html,100)
// 非HTML
\ModStart\Core\Util\StrUtil::limit($text,100,'...')
2
3
4
限制输出 100 个字符
# 其它格式
// 限定浮点格式,更多参考 https://www.php.net/manual/en/function.sprintf.php
sprintf('%0.2f', 3.14159)
2
# 当前网址
以访问 http://example.com/test/path?a=b
为例
// /test/path
\ModStart\Core\Input\Request::path()
// http://example.com/test/path?a=b
\ModStart\Core\Input\Request::currentPageUrl()
// http://example.com/test/path
\ModStart\Core\Input\Request::currentPageUrlWithOutQueries()
2
3
4
5
6
# 当前页面URL
获取当前访问页面完整地址,通常用于生成二维码等
\ModStart\Core\Input\Request::currentPageUrl()
# 二维码生成
生成二维码数据
// 返回base64图片字符串
\ModStart\Core\Util\QrcodeUtil::pngBase64String('ModStart')
2
可直接用于显示,如
<img src="{!! \ModStart\Core\Util\QrcodeUtil::pngBase64String('ModStart') !!}" />
# 获取系统配置
网站配置全部位于 config
数据表中,查找 key
值,通过如下如下函数可以直接获取值,该函数已内置添加了缓存可在视图中多次调用。
modstart_config('xxx','默认值')
# 模板语法
# 显示数据
你可以使用「中括号」包住变量以显示传递至 Blade 视图的数据。就如以下的路由设置一样:
return view('welcome', ['name' => 'Samantha']);
你可以像这样显示 name 变量的内容:
Hello, {{ $name }}.
显示数据或默认值
此写法兼容Laravel5和Laravel9+
{{ empty($name) ? '默认值' : $name }}
当然也不是说一定只能显示传递至视图的变量内容。你也可以显示 PHP 函数的结果。实际上,你可以放置任何你想要的 PHP 代码到 Blade 显示的语法里面:
目前的 UNIX 时间戳为 {{ time() }}。
注意:Blade 的 语法会自动调用 PHP htmlentites 函数来防御 XSS 攻击。
# 条件判断 if
你可以使用 @if、@elseif、@else 及 @endif 命令建构 if 表达式。这些命令的功能等同于在 PHP 中的语法:
@if (count($records) === 1)
我有一条记录!
@elseif (count($records) > 1)
我有多条记录!
@else
我没有任何记录!
@endif
2
3
4
5
6
7
# 循环 for foreach
除了条件表达式外,Blade 也支持 PHP 的循环结构:
@for ($i = 0; $i < 10; $i++)
目前的值为 {{ $i }}
@endfor
@foreach ($users as $user)
<p>此用户为 {{ $user->id }}</p>
@endforeach
@forelse ($users as $user)
<li>{{ $user->name }}</li>
@empty
<p>没有用户</p>
@endforelse
@while (true)
<p>我永远都在跑循环。</p>
@endwhile
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 定义页面布局
使用 Blade 模板的两个主要优点为 模板继承 与 区块。
让我们先通过一个简单的例子来上手。首先,我们需要确认一下「主要的」页面布局。大多数的网页应用程序在不同页面都保持着相同的布局方式,这种布局在这单个 Blade 视图中可以很方便的定义:
<html>
<head>
<title>应用程序名称 - @yield('title')</title>
</head>
<body>
@section('sidebar')
这是主要的侧边栏。
@show
<div class="container">
@yield('content')
</div>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
如你所见,这个文件包含了传统的 HTML 语法。不过,请注意 @section 与 @yield 命令。正如其名,@section 命令定义一个内容区块,而 @yield 命令被用来 “显示指定区块” 的内容。
现在,我们已经定义好了这个应用程序的布局,让我们接着来定义一个继承此布局的子页面。
# 继承页面布局
当正在定义子页面时,你可以使用 Blade 的 @extends 命令指定子页面应该「继承」哪一个布局。当视图 @extends Blade 的布局之后,即可使用 @section 命令将内容注入于布局的区块中。切记,如上述例子所见,这些区块的内容都会使用 @yield 显示在布局中:
@extends('theme.pc.default.frame')
@section('title', '页面标题')
@section('sidebar')
@parent
<p>这边会附加在主要的侧边栏。</p>
@endsection
@section('content')
<p>这是我的主要内容。</p>
@endsection
2
3
4
5
6
7
8
9
10
11
12
在这个例子中,sidebar 区块利用了 @parent 命令增加(而不是覆盖)内容至布局的侧边栏。@parent 命令会在视图输出时被置换成布局的内容。
# 大括号不转义输出
由于许多 JavaScript 框架也使用「大括号」在浏览器中显示指定的表达式,因此可以使用 @ 符号来告知 Blade 渲染引擎该表达式应该维持原样。举个例子:
Hello, @{{ name }}.
在这个例子中,@ 符号会被 Blade 移除。而且,Blade 引擎会保留 表达式,如此一来便可跟其它 JavaScript 框架一起应用。
# 显示未转义过的数据
在默认情况下,Blade 模板中的 表达式将会自动调用 PHP 的 htmlentities 函数,以避免 XSS 攻击。如果你不希望你的数据被转义,可以使用下列的语法:
Hello, {!! $name !!}.
注意:要非常小心处理用户提供的字符串,请总是使用双大括号语法来转义内容中的 HTML 元素,以避免 XSS 攻击。
# 引入子视图
Blade 的 @include 命令用来引入已存在的视图,所有在父视图的可用变量在被引入的视图中都是可用的。
@include('share.header')
尽管被引入的视图会继承父视图中的所有数据,你也可以通过传递额外的数组数据至被引入的页面:
@include('view.name', ['some' => 'data'])
使用说明:
@include('module::Xxx.View.pc.a.b')
表示包含路径module/Xxx/View/pc/a/b.blade.php
视图文件
@include('theme.default.pc.a.b')
表示包含路径resources/views/theme/default/pc/a/b.blade.php
视图文件如果视图文件以
module::
开头,表示是目录module/
中的视图,否则为resources/views/theme/
中的视图
# 当数据存在时输出
有时候你想要输出一个变量,但你并不确定这个变量是否已被设置。我们可以用像这样的冗长 PHP 代码表达:
{{ isset($name) ? $name : '默认值' }}
在这个例子中,如果 $name 变量存在,它的值将会被显示出来。但是,如果这个变量不存在,便会显示 默认值
。
# 注释
Blade 也允许在页面中定义注释,然而,跟 HTML 的注释不同的是,Blade 注释不会被包含在应用程序返回的 HTML 内:
{{-- 此注释将不会出现在渲染后的 HTML --}}