brunolobo/widgets 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

brunolobo/widgets

Composer 安装命令:

composer require brunolobo/widgets

包简介

Pacote de widgets originalmente criado por Arrilot, otimizado para uso no Pacto por Brunolobo.

关键字:

README 文档

README

Pacote de Widgets originalmente criado pelo Arrilot e adaptado por Brunolobo para uso no PactoCRM

Instalação

  1. composer require brunolobo/widgets

Para Laravel >= 5.5, apenas isso. Para Laravel < 5.5, continue lendo.

  1. Registrar o service provider no app.php
<?php

'providers' => [
    ...
    Brunolobo\Widgets\ServiceProvider::class,
],
?>
  1. Adicionar os facades também.
<?php

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

Uso

Considere que vamos criar um widget para exibir as últimas notícias na página.

Primeiro de tudo é criar um novo Widget com o comando artisan.

php artisan make:widget RecentNews

Este comando gera 2 arquivos:

  1. resources/views/widgets/recent_news.blade.php é uma view vazia.

Adicione a opção "--plain" se você não precisa de uma view.

  1. app/Widgets/RecentNews é uma classe de 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,
        ]);
    }
}

Nota: Você pode usar seus próprios .stubs se precisar. Publique os arquivos de configuração para mudar os paths.

O último passo é chamar o widget. Você tem algumas formas de fazer isso.

@widget('recentNews')

ou

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

ou então

{{ Widget::recentNews() }}

Não existe diferença entre os comandos, use conforme a sua preferência.

Passando variaveis para o widget

Pelo array de configuração

Imagine que vamos mostrar 5 notícias no widget de notícias, mas em alguns lugares exibiremos 10. Isso é facilmente conseguido com o uso da variável $config:

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

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

['count' => 10] é um array de configuração que é acessado por $this->config.

O array ed configuração está disponível em todo widget.

Nota: Campos do array de configuração não especificados na criação do widget não serão atualizados:

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

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

Nota 2: Você pode querer (mas provavelmente não deve) criar seu próprio BaseWidget e herdar a partir dele. Tudo bem. A única barreira neste caso é merger as configurações padrão entre pai e filho. Neste caso faça o seguinte:

  1. Não adicione a linha protected $config = [...] no filho.

  2. Adicione conforme abaixo:

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

    parent::__construct($config);
}

Diretamente

Você pode passar parâmetros diretamente para o metodo run().

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

O método run() é resolvido via Service Container, então a injeção no método está disponível.

Namespaces

Por padrão o pacote tenta encontrar seu widget no namespace App\Widgets.

Você pode alterar isso publicando a configuração do pacote (php artisan vendor:publish --provider="Brunolobo\Widgets\ServiceProvider") e setando a propriedade default_namespace.

Ainda que usar o namespace padrão seja muito conveniente, em alguns casos você pode desejar mais flexibilidade. Por exemplo, se você tem dezenas de widgets faz sentido telos em diferentes 'pastas namespaced'.

Sem problema, você tem várias formas de chamar esses widgets:

  1. Passar o nome completo a partir do default_namespace (basically App\Widgets) para o método run().
@widget('News\RecentNews', $config)
  1. Usar notação de ponto.
@widget('news.recentNews', $config)
  1. FQCN também é uma opção.
@widget('\App\Http\Some\Namespace\Widget', $config)

Widgets assíncronos

Em alguns casos é necessário carregar o widget com AJAX.

Isso é conseguido de forma extremamente simples! O que você precisa é mudar o facade ou diretiva blade - Widget:: => AsyncWidget::, @widget => @asyncWidget.

Os parâmetros do widget são encriptados e enviados por ajax por debaixo dos panos. Então espere que os dados sejam encodados com json_encoded() e json_decoded() para desencodar.

Nota: Você pode desligar a encriptação para um determinado widget setando a variável public $encryptParams = false; nele. No entanto esta ação deixa os parâmetros do widget publicamente acessíveis, então tenha certeza de não deixar nenhum ponto de vulnerabilidade. Por exemplo, se você passar o user_id como parâmetro com a encriptação desligada, é interessante acrescentar outra variável de controle dentro do widget.

Nota: Você pode setar use_jquery_for_ajax_calls para true no arquivo de configuração para usar chamadas ajax caso queira.

Por padrão, nada é exibido até que a chamada ajax tenha finalizado.

Isto pode ser customizado com a adição do método placeholder() na classe do widget.

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

Nota: Se você precisa fazer alguma coisa com o pacote de rotas para carregar assincronamente o widget (se você roda em uma subpasta http://site.com/app/) você precisa copiar Brunolobo\Widgets\ServiceProvider para a pasta app, modificar de acordo com suas necessidades e registrar no Laravel.

Widgets recarregáveis

Você pode ir além e atualizar o widget automaticamente a cada N segundos.

Basta setar a propriedade $reloadTimeout do widget e está feito.

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

Tanto widgets sync quanto async tornam-se recarregáveis.

Você deve usar essa função com cuidado, pois pode facilmente sobrecarregar seu aplicativo caso as chamadas ajax tenham tempo muito curto. Considere usar web sockets também mas eles são mais difíceis de configurar.

Container

Os widgets necessitam de alguma interação DOM então todos concentram suas saídas em um containet html. Este container é definido pelo método AbstractWidget::container() e também pode ser customizado.

/**
 * 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"',
    ];
}

Nota: Não são suportados widgets em cascata.

Cache

Também existe uma forma simples de fazer o cache do widget. Basta setar a propriedade $cacheTime no widget e pronto.

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

O cache é desligado por padrão. Uma cache key é criada pelo widget para controle. Você pode sobrescrever o método cacheKey se julgar necessário.

Widget groups (extra)

Em alguns casos o Blade é perfeito para setar a posição e ordem dos widgets. No entanto, algumas vezes você pode ter um comportamento diferente:

// 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() pode ser omitido.

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

é igual a

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

Você pode configurar um separador que irá aparecer entre os widgets de um grupo. Widget::group('sidebar')->setSeparator('<hr>')->...;

Você pode encapsular cada widget de um grupo usando o método wrap method como abaixo:

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>";
})->...;

Removendo widgets de um grupo

Existem algumas formas de remover um ou mais widgets de um grupo depois que eles já estiverem adicionados.

  1. Remover um widget pelo unique 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. Remover todos os widgets com nome específico.
Widget::group('sidebar')->addWidget('files');
Widget::group('sidebar')->addAsyncWidget('files');
Widget::group('sidebar')->removeByName('files'); // Widget group está vazio
  1. Remover todos os widgets de uma posição específica.
Widget::group('sidebar')->position(42)->addWidget('files');
Widget::group('sidebar')->position(42)->addAsyncWidget('files');
Widget::group('sidebar')->removeByPosition(42); // Widget group está vazio
  1. Remover todos os widgets de uma vez.
Widget::group('sidebar')->addWidget('files');
Widget::group('sidebar')->addAsyncWidget('files');
Widget::group('sidebar')->removeAll(); // Widget group está vazio

Checando o estado de um grupo

Widget::group('sidebar')->isEmpty(); // bool

Widget::group('sidebar')->any(); // bool

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

brunolobo/widgets 适用场景与选型建议

brunolobo/widgets 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 71 次下载、GitHub Stars 达 0, 最近一次更新时间为 2018 年 01 月 26 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「pactocrm」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 brunolobo/widgets 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 brunolobo/widgets 我们能提供哪些服务?
定制开发 / 二次开发

基于 brunolobo/widgets 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 71
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 1
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 1
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2018-01-26