{"id":28438088,"url":"https://github.com/zanysoft/laravel-widgets","last_synced_at":"2025-10-29T00:11:23.826Z","repository":{"id":57089309,"uuid":"140398584","full_name":"zanysoft/laravel-widgets","owner":"zanysoft","description":"A powerful alternative to view composers. Asynchronous widgets, reloadable widgets, console generator, caching - everything you can imagine.","archived":false,"fork":false,"pushed_at":"2022-08-03T12:25:14.000Z","size":39,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-06T00:43:12.286Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zanysoft.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-07-10T08:05:28.000Z","updated_at":"2024-12-20T10:35:19.000Z","dependencies_parsed_at":"2022-08-20T16:00:37.822Z","dependency_job_id":null,"html_url":"https://github.com/zanysoft/laravel-widgets","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/zanysoft/laravel-widgets","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zanysoft%2Flaravel-widgets","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zanysoft%2Flaravel-widgets/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zanysoft%2Flaravel-widgets/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zanysoft%2Flaravel-widgets/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zanysoft","download_url":"https://codeload.github.com/zanysoft/laravel-widgets/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zanysoft%2Flaravel-widgets/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262452328,"owners_count":23313420,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-06T00:39:12.106Z","updated_at":"2025-10-29T00:11:23.718Z","avatar_url":"https://github.com/zanysoft.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Latest Stable Version](https://poser.pugx.org/zanysoft/laravel-widgets/v/stable.svg)](https://packagist.org/packages/zanysoft/laravel-widgets/)\n[![Total Downloads](https://img.shields.io/packagist/dt/zanysoft/laravel-widgets.svg)](https://packagist.org/packages/zanysoft/laravel-widgets)\n[![Build Status](https://img.shields.io/travis/zanysoft/laravel-widgets/master.svg)](https://travis-ci.org/zanysoft/laravel-widgets)\n[![Scrutinizer Quality Score](https://img.shields.io/scrutinizer/g/zanysoft/laravel-widgets/master.svg)](https://scrutinizer-ci.com/g/zanysoft/laravel-widgets/)\n\n# Widgets for Laravel\n\n*A powerful alternative to view composers. Asynchronous widgets, reloadable widgets, console generator, caching - everything that you can imagine.*\n\n## Installation\n\nRun ```composer require zanysoft/laravel-widgets```\n\nLaravel \u003e=5.5 uses Package Auto-Discovery, so you don't need to manually add the ServiceProvider and Facades\n\n1) Register a service provider in the `app.php` configuration file if not auto-discover\n\n```php\n\u003c?php\n\n'providers' =\u003e [\n    ...\n    ZanySoft\\Widgets\\ServiceProvider::class,\n],\n?\u003e\n```\n\n2) Add some facades here too if not auto-discover.\n\n```php\n\u003c?php\n\n'aliases' =\u003e [\n    ...\n    'Widget'       =\u003e ZanySoft\\Widgets\\Facade::class,\n    'AsyncWidget'  =\u003e ZanySoft\\Widgets\\AsyncFacade::class,\n],\n?\u003e\n```\n\n## Usage\n\nLet's consider that we want to make a list of recent news and reuse it in several views.\n\nFirst of all we can create a Widget class using the artisan command provided by the package.\n```bash\nphp artisan make:widget RecentNews\n```\nThis command generates two files:\n\n1) `resources/views/widgets/recent_news.blade.php` is an empty view. \n\nAdd \"--plain\" option if you do not need a view.\n\n2) `app/Widgets/RecentNews` is a widget class.\n\n```php\n\u003c?php\n\nnamespace App\\Widgets;\n\nuse ZanySoft\\Widgets\\AbstractWidget;\n\nclass RecentNews extends AbstractWidget\n{\n    /**\n     * The configuration array.\n     *\n     * @var array\n     */\n    protected $config = [];\n\n    /**\n     * Treat this method as a controller action.\n     * Return view() or other content to display.\n     */\n    public function run()\n    {\n        //\n\n        return view('widgets.recent_news', [\n            'config' =\u003e $this-\u003econfig,\n        ]);\n    }\n}\n```\n\n\u003e Note: You can use your own stubs if you need. Publish config file to change paths.\n\nThe last step is to call the widget.\nThere are several ways to do so.\n\n```php\n@widget('recentNews')\n```\nor\n```php\n{{ Widget::run('recentNews') }}\n```\nor even\n```php\n{{ Widget::recentNews() }}\n```\n\nThere is no real difference between these. The choice is up to you.\n\n## Passing variables to widget\n\n### Via config array\n\nLet's carry on with the \"recent news\" example.\n\nImagine that we usually need to show *five* news, but in some views we need to show *ten*.\nThis can be easily achieved by:\n\n```php\nclass RecentNews extends AbstractWidget\n{\n    ...\n    protected $config = [\n        'count' =\u003e 5\n    ];\n    ...\n}\n\n...\n@widget('recentNews') // shows 5\n@widget('recentNews', ['count' =\u003e 10]) // shows 10\n```\n`['count' =\u003e 10]` is a config array that can be accessed by $this-\u003econfig.\n\nConfig array is available in every widget method so you can use it to configure placeholder and container too (see below)\n\n\u003e Note: Config fields that are not specified when you call a widget aren't overridden:\n\n```php\nclass RecentNews extends AbstractWidget\n{\n    ...\n    protected $config = [\n        'count' =\u003e 5,\n        'foo'   =\u003e 'bar'\n    ];\n    \n    ...\n}\n\n@widget('recentNews', ['count' =\u003e 10]) // $this-\u003econfig['foo'] is still 'bar'\n```\n\n\u003e Note 2: You may want (but you probably don't) to create your own BaseWidget and inherit from it.\nThat's fine. The only edge case is merging config defaults from a parent and a child. \nIn this case do the following:\n\n1) Do not add `protected $config = [...]` line to a child.\n\n2) Instead add defaults like this:\n\n```php\npublic function __construct(array $config = [])\n{\n    $this-\u003eaddConfigDefaults([\n        'child_key' =\u003e 'bar'\n    ]);\n\n    parent::__construct($config);\n}\n```\n\n### Directly\n\nYou can also choose to pass additional parameters to `run()` method directly.\n\n```php\n@widget('recentNews', ['count' =\u003e 10], 'date', 'asc')\n...\npublic function run($sortBy, $sortOrder) { }\n...\n```\n\n`run()` method is resolved via Service Container, so method injection is also available here.\n\n## Namespaces\n\nBy default the package tries to find your widget in the ```App\\Widgets``` namespace.\n\nYou can override this by publishing package config (```php artisan vendor:publish --provider=\"ZanySoft\\Widgets\\ServiceProvider\"```) and setting `default_namespace` property.\n\nAlthough using the default namespace is very convenient, in some cases you may wish to have more flexibility. \nFor example, if you've got dozens of widgets it makes sense to group them in namespaced folders.\n\nNo problem, there are several ways to call those widgets:\n\n1) Pass a full widget name from the `default_namespace` (basically `App\\Widgets`) to the `run` method.\n```php\n@widget('News\\RecentNews', $config)\n```\n\n2) Use dot notation.\n```php\n@widget('news.recentNews', $config)\n```\n\n3) FQCN is also an option.\n```php\n@widget('\\App\\Http\\Some\\Namespace\\Widget', $config)\n```\n\n## Asynchronous widgets\n\nIn some situations it can be very beneficial to load widget content with AJAX.\n\nFortunately, this can be achieved very easily!\nAll you need to do is to change facade or blade directive - `Widget::` =\u003e `AsyncWidget::`, `@widget` =\u003e `@asyncWidget`\n\nWidget params are encrypted (by default) and sent via ajax call under the hood. So expect them to be `json_encoded()` and `json_decoded()` afterwards.\n\n\u003e Note: You can turn encryption off for a given widget by setting `public $encryptParams = false;` on it. However, this action will make widget params publicly accessible, so please make sure to not leave any vulnerabilities.\nFor example, if you pass something like user_id through widget params and turn encryption off, you do need to add one more access check inside the widget.\n\n\u003e Note: You can set `use_jquery_for_ajax_calls` to `true` in the config file to use it for ajax calls if you want to.\n\nBy default nothing is shown until ajax call is finished.\n\nThis can be customized by adding a `placeholder()` method to the widget class.\n\n```php\npublic function placeholder()\n{\n    return 'Loading...';\n}\n```\n\n\u003e Side note: If you need to do something with the routes package used to load async widgets (e.g. you run app in a subfolder http://site.com/app/) you need to copy ZanySoft\\Widgets\\ServiceProvider to your app, modify it according to your needs and register it in Laravel instead of the former one.\n\n## Reloadable widgets\n\nYou can go even further and automatically reload widget every N seconds.\n\nJust set the `$reloadTimeout` property of the widget class and it is done.\n\n```php\nclass RecentNews extends AbstractWidget\n{\n    /**\n     * The number of seconds before each reload.\n     *\n     * @var int|float\n     */\n    public $reloadTimeout = 10;\n}\n```\n\nBoth sync and async widgets can become reloadable.\n\nYou should use this feature with care, because it can easily spam your app with ajax calls if timeouts are too low.\nConsider using web sockets too but they are way harder to set up.\n\n## Container\n\nAsync and Reloadable widgets both require some DOM interaction so they wrap all widget output in a html container.\nThis container is defined by `AbstractWidget::container()` method and can be customized too.\n\n```php\n/**\n * Async and reloadable widgets are wrapped in container.\n * You can customize it by overriding this method.\n *\n * @return array\n */\npublic function container()\n{\n    return [\n        'element'       =\u003e 'div',\n        'attributes'    =\u003e 'style=\"display:inline\" class=\"zanysoft-widget-container\"',\n    ];\n}\n```\n\n\u003e Note: Nested async or reloadable widgets are not supported.\n\n## Caching\n\nThere is also a simple built-in way to cache entire widget output.\nJust set $cacheTime property in your widget class and you are done.\n\n```php\nclass RecentNews extends AbstractWidget\n{\n    /**\n     * The number of minutes before cache expires.\n     * False means no caching at all.\n     *\n     * @var int|float|bool\n     */\n    public $cacheTime = 60;\n}\n```\n\nNo caching is turned on by default.\nA cache key depends on a widget name and each widget parameter.\nOverride ```cacheKey``` method if you need to adjust it.\n\n### Cache tagging\n\nWhen tagging is supported ([see the Laravel cache documentation](https://laravel.com/docs/cache#cache-tags)) and to \nsimplify cache flushing, a tag `widgets` is assigned by default to all widgets. \nYou can define one or more additional tags to your widgets by setting the values \nin the `$cacheTags` property in your widget class. Example :\n\n```php\nclass RecentNews extends AbstractWidget\n{\n    /**\n     * Cache tags allow you to tag related items in the cache \n     * and then flush all cached values that assigned a given tag.\n     *\n     * @var array\n     */\n    public $cacheTags = ['news', 'frontend'];\n}\n```\n\nFor this example, if you need to flush :\n\n```php\n// Clear widgets with the tag news\nCache::tags('news')-\u003eflush();\n\n// Clear widgets with the tag news OR backend\nCache::tags(['news', 'frontend'])-\u003eflush();\n\n// Flush all widgets cache\nCache::tags('widgets')-\u003eflush();\n```\n\n## Widget groups (extra)\n\nIn most cases Blade is a perfect tool for setting the position and order of widgets.\nHowever, sometimes you may find useful the following approach:\n\n```php\n// add several widgets to the 'sidebar' group anywhere you want (even in controller)\nWidget::group('sidebar')-\u003eposition(5)-\u003eaddWidget('widgetName1', $config1);\nWidget::group('sidebar')-\u003eposition(4)-\u003eaddAsyncWidget('widgetName2', $config2);\n\n// display them in a view in the correct order\n@widgetGroup('sidebar')\n// or \n{{ Widget::group('sidebar')-\u003edisplay() }}\n```\n\n`position()` can be omitted from the chain.\n\n`Widget::group('sidebar')-\u003eaddWidget('files');` \n\nequals\n\n`Widget::group('sidebar')-\u003eposition(100)-\u003eaddWidget('files');`\n\nYou can set a separator that will be display between widgets in a group.\n`Widget::group('sidebar')-\u003esetSeparator('\u003chr\u003e')-\u003e...;`\n\nYou can also wrap each widget in a group using `wrap` method like that.\n```php\nWidget::group('sidebar')-\u003ewrap(function ($content, $index, $total) {\n    // $total is a total number of widgets in a group.\n    return \"\u003cdiv class='widget-{$index}'\u003e{$content}\u003c/div\u003e\";\n})-\u003e...;\n```\n\n### Removing widgets from a group\n\nThere is a couple of ways to remove widget/widgets from a group after they've been already added.\n\n1) Remove one widget by its unique `id`\n```php\n$id1 = Widget::group('sidebar')-\u003eaddWidget('files');\n$id2 = Widget::group('sidebar')-\u003eaddAsyncWidget('files');\nWidget::group('sidebar')-\u003eremoveById($id1); // There is only second widget in the group now\n```\n\n2) Remove all widgets with specific name\n```php\nWidget::group('sidebar')-\u003eaddWidget('files');\nWidget::group('sidebar')-\u003eaddAsyncWidget('files');\nWidget::group('sidebar')-\u003eremoveByName('files'); // Widget group is empty now\n```\n\n3) Remove all widgets that are placed on a specific position.\n```php\nWidget::group('sidebar')-\u003eposition(42)-\u003eaddWidget('files');\nWidget::group('sidebar')-\u003eposition(42)-\u003eaddAsyncWidget('files');\nWidget::group('sidebar')-\u003eremoveByPosition(42); // Widget group is empty now\n```\n\n4) Remove all widgets at once.\n```php\nWidget::group('sidebar')-\u003eaddWidget('files');\nWidget::group('sidebar')-\u003eaddAsyncWidget('files');\nWidget::group('sidebar')-\u003eremoveAll(); // Widget group is empty now\n```\n\n### Checking the state of a group\n\n`Widget::group('sidebar')-\u003eisEmpty(); // bool`\n\n`Widget::group('sidebar')-\u003eany(); // bool`\n\n`Widget::group('sidebar')-\u003ecount(); // int`\n\n## Namespaces for third party packages (extra)\n\nIn some cases, it may be useful to deliver widgets with your own packages. For example, if your package allows \nyou to manage news, it would be convenient to have immediately configurable widgets, ready for display, directly \ndelivered with your package.\n\nTo avoid having to use the fqcn each time, you can set a widget namespace into your package provider. This way the \nwidgets from your package can be more easily identified, and especially the syntax will be shorter.\n\nTo do that, all you have to do is to register the namespace in your package service provider :\n\n```php\npublic function boot() \n{\n    app('zanysoft.widget-namespaces')-\u003eregisterNamespace('my-package-name', '\\VendorName\\PackageName\\Path\\To\\Widgets');\n}\n```\n\nAfter that you can use the namespace in your views :\n\n```php\n@widget('my-package-name::foo.bar')\n\n// is equivalent to\n@widget('\\VendorName\\PackageName\\Path\\To\\Widgets\\Foo\\Bar')\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzanysoft%2Flaravel-widgets","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzanysoft%2Flaravel-widgets","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzanysoft%2Flaravel-widgets/lists"}