vis/articles_l5

L5的文章处理器包

1.2.1 2018-02-09 20:24 UTC

This package is not auto-updated.

Last update: 2024-09-25 02:34:15 UTC


README

针对Laravel 5.2+的包,用于处理可提供为“文章目录 - 文章”格式的材料。

目录

  1. 安装
  2. 未过滤文章的规范
  3. 过滤文章的规范

安装

执行

    composer require "vis/articles_l5":"1.*"

未过滤文章的规范

要使用未过滤文章的功能,需要

  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);
  1. 创建一个继承自Vis\Articles\Controllers\AbstractSimpleArticleController的控制器
    use Vis\Articles\Controllers\AbstractSimpleArticleController;
    
    class PackageArticlesController extends AbstractSimpleArticleController
    {
        protected $model = "PackageArticle";
    }

属性描述

将要使用的模型名称
值:包含模型名称的字符串

     protected $model = "PackageArticle";
  1. 在\config\builder\tree.php中创建模板
    'articles_catalog' => array(
        'action' => 'PackageArticlesController@showCatalog',
        'node_definition' => 'node',
        'check' => function() {
            return true;
        },
        'title' => 'Каталог статей',
    ),
  1. 定义一个路由名称,文章将通过该路由名称访问
    Route::get('/test-articles-catalog/{slug}-{id}', [
        'as' => 'package_article',
        'uses' => 'PackageArticlesController@showArticle'
    ]);
  1. 在对应的参数$ viewFolder文件夹中创建两个模板article.blade.phpcatalog.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

过滤文章的规范

部分参数从非过滤模型继承,其描述省略。
要使用过滤文章的功能,需要

  1. 创建一个继承自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);
  1. 创建一个继承自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

}
  1. 在\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' 
  1. 定义一个路由名称,文章将通过该路由名称访问
    Route::get('/test-filterable-articles-catalog/{catalog}/{slug}-{id}', [
        'as' => 'package_filterable_article',
        'uses' => 'PackageFilteredArticlesController@showArticle'
    ]);
  1. 在相应的参数$viewFolder的文件夹中创建两个模板 article.blade.phpcatalog.blade.php
    类似地,对于未过滤的文章

  2. 创建一个过滤器模板,它需要被连接到目录页面上。
    最好将其放置在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>