brunolobo/widgets

由Arrilot最初创建的widgets包,针对Brunolobo协议优化。

v1 2018-01-26 15:58 UTC

This package is not auto-updated.

Last update: 2024-09-20 20:31:33 UTC


README

由Arrilot最初创建并由Brunolobo修改,用于PactoCRM的Widgets包

安装

  1. composer require brunolobo/widgets

对于Laravel >= 5.5,只需这样做。对于Laravel < 5.5,请继续阅读。

  1. app.php中注册service provider
<?php

'providers' => [
    ...
    Brunolobo\Widgets\ServiceProvider::class,
],
?>
  1. 也添加facades
<?php

'aliases' => [
    ...
    'Widget'       => Brunolobo\Widgets\Facade::class,
    'AsyncWidget'  => Brunolobo\Widgets\AsyncFacade::class,
],
?>

使用方法

假设我们要创建一个在页面上显示最新新闻的小部件。

首先,使用artisan命令创建一个新的Widget。

php artisan make:widget RecentNews

此命令生成2个文件

  1. resources/views/widgets/recent_news.blade.php是一个空的视图。

如果您不需要视图,请添加“--plain”选项。

  1. app/Widgets/RecentNews是一个Widget类。
<?php

namespace App\Widgets;

use Brunolobo\Widgets\AbstractWidget;

class RecentNews extends AbstractWidget
{
    /**
     * The configuration array.
     *
     * @var array
     */
    protected $config = [];

    /**
     * Treat this method as a controller action.
     * Return view() or other content to display.
     */
    public function run()
    {
        //

        return view('widgets.recent_news', [
            'config' => $this->config,
        ]);
    }
}

注意:如果您需要,可以使用自己的.stubs。发布配置文件以更改路径。

最后一步是调用小部件。您有多种方法可以这样做。

@widget('recentNews')

或者

{{ Widget::run('recentNews') }}

或者

{{ Widget::recentNews() }}

这些命令之间没有区别,根据您的喜好使用。

向小部件传递变量

通过配置数组

假设我们要在新闻小部件中显示5条新闻,但在某些地方显示10条。这可以通过使用变量$config轻松实现。

class RecentNews extends AbstractWidget
{
    ...
    protected $config = [
        'count' => 5
    ];
    ...
}

...
@widget('recentNews') // shows 5
@widget('recentNews', ['count' => 10]) // shows 10

['count' => 10]是一个配置数组,通过$this->config访问。

配置数组在整个小部件中都是可用的。

注意:未在创建小部件时指定的数组字段将不会更新

class RecentNews extends AbstractWidget
{
    ...
    protected $config = [
        'count' => 5,
        'foo'   => 'bar'
    ];
    
    ...
}

@widget('recentNews', ['count' => 10]) // $this->config['foo'] continua sendo 'bar'

注意2:您可能(但可能不应该)创建自己的BaseWidget并从它继承。没问题。这种情况下的唯一障碍是在父亲和子代之间合并默认配置。在这种情况下,请这样做

  1. 不要在子代中添加protected $config = [...]行。

  2. 请按以下方式添加

public function __construct(array $config = [])
{
    $this->addConfigDefaults([
        'child_key' => 'bar'
    ]);

    parent::__construct($config);
}

直接

您可以直接将参数传递给run()方法。

@widget('recentNews', ['count' => 10], 'date', 'asc')
...
public function run($sortBy, $sortOrder) { }
...

run()方法是通过Service Container解析的,因此方法中的注入是可用的。

命名空间

默认情况下,包尝试在命名空间App\Widgets中查找您的widget。

您可以通过发布包配置(php artisan vendor:publish --provider="Brunolobo\Widgets\ServiceProvider")并设置default_namespace属性来更改此设置。

尽管使用默认命名空间非常方便,但在某些情况下,您可能需要更多的灵活性。例如,如果您有数十个小部件,将其组织在不同的命名空间文件夹中是有意义的。

没问题,您有多种方法可以调用这些小部件

  1. default_namespace(基本上是App\Widgets)传递完整的名称到run()方法。
@widget('News\RecentNews', $config)
  1. 使用点符号。
@widget('news.recentNews', $config)
  1. 完全限定名称(FQCN)也是一个选项。
@widget('\App\Http\Some\Namespace\Widget', $config)

异步Widgets

在某些情况下,需要通过AJAX加载小部件。

这非常简单!您需要做的是更改facade或blade指令 - Widget:: > AsyncWidget::@widget > @asyncWidget

小部件参数被加密并通过AJAX在幕后发送。因此,请等待数据被json_encoded()json_decoded()编码和解码。

注意:您可以通过在其中设置变量 public $encryptParams = false; 来关闭特定小部件集的加密。然而,此操作会使小部件的参数公开可访问,因此请确保没有留下任何漏洞点。例如,如果您在禁用加密的情况下传递 user_id 作为参数,则在小部件内部添加另一个控制变量是很有趣的。

注意:您可以在配置文件中将 use_jquery_for_ajax_calls 设置为 true 以使用 AJAX 调用。

默认情况下,直到 AJAX 调用完成之前,不会显示任何内容。

您可以通过在小部件类中添加 placeholder() 方法来自定义此行为。

public function placeholder()
{
    return 'Carregando...';
}

注意:如果您需要在子目录(如 http://site.com/app/)中运行时异步加载小部件,您需要将 Brunolobo\Widgets\ServiceProvider 复制到 app 目录,根据您的需求进行修改,并在 Laravel 中进行注册。

可重新加载的小部件

您还可以进一步设置每 N 秒自动更新小部件。

只需设置小部件的 $reloadTimeout 属性即可。

class RecentNews extends AbstractWidget
{
    /**
     * The number of seconds before each reload.
     *
     * @var int|float
     */
    public $reloadTimeout = 10;
}

同步和异步小部件都变为可重新加载。

您应谨慎使用此功能,因为如果 AJAX 调用时间过短,很容易使您的应用程序过载。也可以考虑使用 WebSockets,但它们的配置更复杂。

容器

小部件需要一些 DOM 交互,因此所有输出都集中在一个 HTML 容器中。此容器由方法 AbstractWidget::container() 定义,也可以进行自定义。

/**
 * Async and reloadable widgets are wrapped in container.
 * You can customize it by overriding this method.
 *
 * @return array
 */
public function container()
{
    return [
        'element'       => 'div',
        'attributes'    => 'style="display:inline" class="brunolobo-widget-container"',
    ];
}

注意:不支持级联小部件。

缓存

还可以通过设置小部件中的 $cacheTime 属性来简单地缓存小部件。

class RecentNews extends AbstractWidget
{
    /**
     * The number of minutes before cache expires.
     * False means no caching at all.
     *
     * @var int|float|bool
     */
    public $cacheTime = 60;
}

默认情况下,缓存是关闭的。小部件会创建一个缓存密钥进行控制。如果需要,您可以覆盖 cacheKey 方法。

小部件组(额外功能)

在某些情况下,Blade 完全适用于设置小部件的位置和顺序。然而,有时您可能需要不同的行为

// add several widgets to the 'sidebar' group anywhere you want (even in controller)
Widget::group('sidebar')->position(5)->addWidget('widgetName1', $config1);
Widget::group('sidebar')->position(4)->addAsyncWidget('widgetName2', $config2);

// display them in a view in the correct order
@widgetGroup('sidebar')
// or 
{{ Widget::group('sidebar')->display() }}

position() 可以省略。

Widget::group('sidebar')->addWidget('files');

等同于

Widget::group('sidebar')->position(100)->addWidget('files');

您可以为组中的小部件配置一个分隔符,该分隔符将在小部件之间显示。 Widget::group('sidebar')->setSeparator('<hr>')->...;

您可以使用下面的方法 wrap 将组中的每个小部件封装起来

Widget::group('sidebar')->wrap(function ($content, $index, $total) {
    // $total is a total number of widgets in a group.
    return "<div class='widget-{$index}'>{$content}</div>";
})->...;

从组中删除小部件

在添加后,有几种方法可以删除一个或多个小部件。

  1. 通过唯一 id 删除小部件。
$id1 = Widget::group('sidebar')->addWidget('files');
$id2 = Widget::group('sidebar')->addAsyncWidget('files');
Widget::group('sidebar')->removeById($id1); // Agora só o segundo wodget está no grupo
  1. 删除所有具有特定名称的小部件。
Widget::group('sidebar')->addWidget('files');
Widget::group('sidebar')->addAsyncWidget('files');
Widget::group('sidebar')->removeByName('files'); // Widget group está vazio
  1. 删除特定位置的所有小部件。
Widget::group('sidebar')->position(42)->addWidget('files');
Widget::group('sidebar')->position(42)->addAsyncWidget('files');
Widget::group('sidebar')->removeByPosition(42); // Widget group está vazio
  1. 一次性删除所有小部件。
Widget::group('sidebar')->addWidget('files');
Widget::group('sidebar')->addAsyncWidget('files');
Widget::group('sidebar')->removeAll(); // Widget group está vazio

检查组的状态

Widget::group('sidebar')->isEmpty(); // 布尔值

Widget::group('sidebar')->any(); // 布尔值

Widget::group('sidebar')->count(); // 整数