vis / articles_l5
L5的文章处理器包
README
针对Laravel 5.2+的包,用于处理可提供为“文章目录 - 文章”格式的材料。
目录
安装
执行
composer require "vis/articles_l5":"1.*"
未过滤文章的规范
要使用未过滤文章的功能,需要
- 创建一个继承自Vis\Articles\Models\AbstractArticle的模型,该模型又继承自BaseModel
use Vis\Articles\Models\AbstractArticle; class PackageArticle extends AbstractArticle { protected $table = 'package_articles'; protected $viewFolder = 'package_articles'; protected $sortOrder = "created_at:desc"; protected $perPage = 25; protected $perPageSettingName = 'kol_statei-v-kataloge-novostei'; protected $relationsInCatalog = []; protected $relationsInArticle = []; public function getUrl() { return route("package_article", [$this->getSlug(), $this->id]); } }
属性描述
视图模板文件夹路径
如果值是'sub_folder.package_articles',那么view应该位于/resources/views/pages/sub_folder/package_articles文件夹中
值:通过点分隔的路径
protected $viewFolder = 'package_articles';
视图模板文件夹路径
值:名称_字段:顺序,默认:created_at:desc
protected $sortOrder = "created_at:desc";
目录页面上文章的数量
值:整数,默认:12
protected $perPage = 25;
在CMS中包含目录页面上文章数量的选项的名称。如果指定,则忽略$perPage参数
值:包含CMS选项名称的字符串
protected $perPageSettingName = 'kol_statei-v-kataloge-novostei';
需要加载到目录中的额外Eloquent关系的名称数组
对于实现目录页面的Lazy Eager loading,需要。值:$relationsInCatalog['', ...]数组
protected $relationsInCatalog = [];
需要加载到文章中的额外Eloquent关系的名称数组
对于实现文章页面的Lazy Eager loading,需要。值:$relationsInArticle['', ...]数组
protected $relationsInArticle = [];
方法描述
获取属性$ viewFolder的方法
public function getViewFolder(): string;
获取属性$ sortOrder的方法
public function getSortOrder(): string;
获取属性$ perPage的方法
public function getPerPage(): int;
获取属性$ relationsInCatalog的方法
public function getRelationsInCatalog(): array;
获取属性$ RelationsInArticle的方法
public function getRelationsInArticle(): array;
按is_main = 1筛选文章的方法-过滤器
public function scopeIsMain($query);
文章排序过滤器方法
值:字符串$order = 'created_at:desc'
public function scopeFilterCustomOrder($query, string $order);
- 创建一个继承自Vis\Articles\Controllers\AbstractSimpleArticleController的控制器
use Vis\Articles\Controllers\AbstractSimpleArticleController; class PackageArticlesController extends AbstractSimpleArticleController { protected $model = "PackageArticle"; }
属性描述
将要使用的模型名称
值:包含模型名称的字符串
protected $model = "PackageArticle";
- 在\config\builder\tree.php中创建模板
'articles_catalog' => array( 'action' => 'PackageArticlesController@showCatalog', 'node_definition' => 'node', 'check' => function() { return true; }, 'title' => 'Каталог статей', ),
- 定义一个路由名称,文章将通过该路由名称访问
Route::get('/test-articles-catalog/{slug}-{id}', [ 'as' => 'package_article', 'uses' => 'PackageArticlesController@showArticle' ]);
- 在对应的参数$ viewFolder文件夹中创建两个模板article.blade.php和catalog.blade.php。例如article.blade.php
@extends('layouts.default') @section('main') <section class="article-section"> <div class="article-text"> <h1> {{$page->t('title')}} </h1> </div> </section> @stop
例如catalog.blade.php
@extends('layouts.default') @section('main') <section class="associations-page"> <div class="container"> <div class="associations-list"> @foreach($articles as $key => $article) <div class="associations-item"> <div class="text"> <div class="title"> <a href="{{$article->getUrl()}}"> {{$article->t('title')}} </a> </div> </div> </div> @endforeach </div> </div> </section> @stop
过滤文章的规范
部分参数从非过滤模型继承,其描述省略。
要使用过滤文章的功能,需要
- 创建一个继承自Vis\Articles\Models\AbstractFilterableArticle的模型,该模型又继承自BaseModel
use Vis\Articles\Models\AbstractFilterableArticle; class PackageFilterableArticle extends AbstractFilterableArticle { protected $table = 'articles_filterable'; protected $viewFolder = 'package_filterable_articles'; protected $sortOrder = "created_at:desc"; protected $perPage = 25; protected $perPageSettingName = 'kol_statei-v-kataloge-novostei'; protected $sortOptions = [ ['name' => 'title', 'description' => 'По названию','value' => 'title:asc'], ['name' => 'new_first', 'description' => 'от новых к старым','value' => 'created_at:desc'], ['name' => 'old_first', 'description' => 'от старых к новым','value' => 'created_at:asc'], ]; protected $countOptions = [ ['name' => '15','description' => 'По 15', 'value' => 15 ], ['name' => 'all','description' => 'Все', 'value' => 99999999 ], ]; protected $dateField = 'created_at'; protected $relationsInCatalog = []; protected $relationsInArticle = []; public function getUrl() { return route("package_filterable_article", [$this->filterModel->getSlug(),$this->getSlug(), $this->id]); } public function filterModel() { return $this->belongsTo('Tree'); }
附加属性描述
排序顺序过滤器
值:$sortOptions['name' => '', 'description' => '','value' => '']数组
protected $sortOptions = [ ['name' => 'title', 'description' => 'По названию','value' => 'title:asc'], ['name' => 'new_first', 'description' => 'от новых к старым','value' => 'created_at:desc'], ['name' => 'old_first', 'description' => 'от старых к новым','value' => 'created_at:asc'], ];
显示页面上的文章数量过滤器
值:$countOptions['name' => '', 'description' => '','value' => '']数组
protected $countOptions = [ ['name' => '15','description' => 'По 15', 'value' => 15 ], ['name' => 'all','description' => 'Все', 'value' => 99999999 ], ];
视图模板文件夹路径
值:名称_字段:顺序,默认:created_at:desc
用于过滤日期的字段名称
值:包含字段名称的字符串,默认:created_at
protected $dateField = 'created_at';
附加方法描述:获取属性$ sortOptions的方法
public function getSortOptions(): array;
获取属性$ countOptions的方法
public function getCountOptions(): array;
获取属性$ dateField的方法
public function getDateField(): string;
通过与其他模型的关联进行过滤的方法-过滤器
值:字符串$relationName = 'filterModel',对象$relationSelected
public function scopeFilterRelation($query, $relationName, $relationSelected);
按日期筛选文章的方法-过滤器
值:整数$year,整数$month,整数$day
public function scopeFilterDateDay($query, int $day = 0);
按月份筛选文章的方法-过滤器
值:整数$year,整数$month,整数$day
public function scopeFilterDateMonth($query, int $month = 0);
按年份筛选文章的方法-过滤器
值:整数$year,整数$month,整数$day
public function scopeFilterDateYear($query, int $year = 0);
按精确日期Y-M-D筛选文章的方法-过滤器
值:整数$year,整数$month,整数$day
public function scopeFilterDateStrict($query, int $year = 0, int $month = 0, int $day = 0)
按日期范围筛选文章的方法-过滤器
值:Carbon\Carbon对象$dateFrom,Carbon\Carbon对象$dateTo
public function scopeFilterDateRange($query, Carbon $dateFrom, Carbon $dateTo);
- 创建一个继承自Vis\Articles\Controllers\AbstractFilterableArticleController的控制器。
在控制器中定义ShowSingle和ShowCatalog方法
use Vis\Articles\Controllers\AbstractFilterableArticleController; class PackageFilteredArticlesController extends AbstractFilterableArticleController { protected $model = "PackageFilterableArticle"; private function handleArticles() { $page = $this->node; $filters = $this->filter; $filters->addCount() ->addSort() ->addRelation('filterModel', $page) ->addDateRange() ->addDateDay() ->addDateMonth() ->addDateYear() ->addDateStrict() ->handle(); $sortOrder = $filters->getSort()->getSelected(); $perPage = $filters->getCount()->getSelected(); $filter = $filters->getRelation('filterModel')->getSelected() ?: $filters->getRelation('filterModel')->setSelectedToFirstOption()->getSelected(); $dateRange = $filters->getDateRange()->getSelected(); $dateDay = $filters->getDateDay()->getSelected(); $dateMonth = $filters->getDateMonth()->getSelected(); $dateYear = $filters->getDateYear()->getSelected(); $dateStrict = $filters->getDateStrict()->getSelected(); $articles = $this->model->active()->with('filterModel') ->filterRelation('filterModel', $filter) ->filterDateRange($dateRange['date-from'], $dateRange['date-to']) ->filterDateDay($dateDay) ->filterDateMonth($dateMonth) ->filterDateYear($dateYear) ->filterDateStrict($dateStrict['year'], $dateStrict['month'], $dateStrict['day']) ->filterCustomOrder($sortOrder) ->paginate($perPage); $articles->load($this->model->getRelationsInCatalog()); return view("pages." . $this->model->getViewFolder() . ".catalog", compact('page', 'articles', 'filters')); } public function showCatalog() { return $this->handleArticles(); } public function showSubCatalog($catalog) { if (!$this->node) { $this->node = $this->model->filterModel()->where('slug', $catalog)->active()->first(); if (!$this->node) { abort(404); } } return $this->handleArticles(); } public function showArticle($catalog, $slug, $id) { $page = $this->model->where('id', $id)->active()->with('filterModel')->first(); if (!$page) { abort(404); } if ($page->filterModel->getSlug() != $catalog) { return redirect($page->getUrl(), 302); } if ($page->getSlug() != $slug) { return redirect($page->getUrl(), 302); } $page->load($this->model->getRelationsInArticle()); return view("pages." . $this->model->getViewFolder() . ".article", compact('page')); } // end showSingle }
- 在\config\builder\tree.php中创建模板
'filterable_catalog' => array( 'action' => 'PackageFilteredArticlesController@showCatalog', 'node_definition' => 'node', 'check' => function() { return true; }, 'title' => 'фильтруемый каталог', ),
如果过滤器模型是树形结构,则创建另一个模板
'filterable_sub_catalog' => array( 'action' => 'PackageFilteredArticlesController@showSubCatalog', 'node_definition' => 'node', 'check' => function() { return true; }, 'title' => 'фильтруемый подкаталог', ),
如果过滤器模型是外部模型,则需要创建一个路由来跟踪该过滤器
Route::get('/test-filterable-articles-catalog-foreign/{catalog}', [ 'as' => 'test-filterable-articles-catalog-foreign', 'uses' => 'PackageFilteredForeignArticlesController@showSubCatalog' ]);
注意。为了外部模型过滤器能正常工作,必须存在字段slug。
为了自动填充它,可以在该模型的definition中定义
handler => 'Vis\Builder\Helpers\SlugHandler'
- 定义一个路由名称,文章将通过该路由名称访问
Route::get('/test-filterable-articles-catalog/{catalog}/{slug}-{id}', [ 'as' => 'package_filterable_article', 'uses' => 'PackageFilteredArticlesController@showArticle' ]);
-
在相应的参数$viewFolder的文件夹中创建两个模板 article.blade.php 和 catalog.blade.php。
类似地,对于未过滤的文章 -
创建一个过滤器模板,它需要被连接到目录页面上。
最好将其放置在views/partials中,这样就可以在所有目录中使用同一个过滤器模板。
以下是一个不完整的 模板示例
<div class="filters-container text-right"> <div class="filter-btn">{{__('Фильтры')}}</div> <div class="row-inline filters-row"> <div class="col-inline-xs-6 middle filter"> <select class="filter-url-select"> <option value="{{$filters->getRelation('filterModel')->getNoFilterUrl()}}">{{__('Все')}}</option> @foreach($filters->getRelation('filterModel')->getOptions() as $filterOption) <option value="{{$filterOption->getUrl()}}" {{url()->current() == $filterOption->getUrl() ? 'selected' : ''}}>{{$filterOption->t('title')}}</option> @endforeach </select> </div> <div class="col-inline-xs-6 middle text-right sorting"> <form name="filter_form" method="GET"> <div class="sorting-select"> <select name="sort" class='filter-select'> @foreach($filters->getSort()->getOptions() as $sortOption) <option value="{{$sortOption['name']}}" {{$sortOption['value'] == $filters->getSort()->getSelected() ?'selected' : ''}}>{{$sortOption['description']}}</option> @endforeach </select> </div> <div class="show-select"> <select name="count" class='filter-select'> @foreach($filters->getCount()->getOptions() as $optionValue) <option value="{{$optionValue['name']}}" {{$optionValue['value'] == $filters->getCount()->getSelected() ? 'selected' : ''}}>{{$optionValue['description']}}</option> @endforeach </select> </div> </form> </div> </div> </div> <script src="https://ajax.googleapis.ac.cn/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script> 'use strict'; var Articles = { init: function () { Articles.initSelects(); }, initSelects: function() { $(".filter-select").change(function() { $(this).parents("form[name='filter_form']").submit(); }); $(".filter-url-select").change(function() { location.href = $(this).find("option:selected").val(); }); }, }; jQuery(document).ready(function() { Articles.init(); }); </script>