• Stars
    star
    902
  • Rank 50,637 (Top 1.0 %)
  • Language
    PHP
  • License
    MIT License
  • Created almost 8 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A minimal package to help you make your laravel application cleaner and faster.

Laravel Widgetize

widgetize_header

Maintainability Quality Score Latest Stable Version Awesome Laravel Monthly Downloads Code Coverage

๐ŸŽ€๐ŸŽ€ "cleaner code" โž• "easy caching" ๐ŸŽ€๐ŸŽ€

Built with โค๏ธ for every smart laravel developer


More readings:

This page may look long and boring to read at first, but bear with me!!!

I bet if you read through it you won't get disappointed at the end.So let's Go... ๐Ÿ‡


Installation: โฌ‡๏ธ

composer require imanghafoori/laravel-widgetize

๐Ÿ”Œ (For Laravel <=5.4) Next, you must add the service provider to config/app.php ๐Ÿ”Œ

'providers' => [
    // for laravel 5.4 and below
    Imanghafoori\Widgets\WidgetsServiceProvider::class,
];

Publish your config file

php artisan vendor:publish

๐Ÿ”ฅ And you will be on fire!๐Ÿ”ฅ

php artisan make:widget MySexyWidget

A lot of docs are included in the generated widget file so it is not needed to memorize or even read the rest of this page. You can jump right-in and start using it.

Overview:

This package helps you in:

  • Page Partial Caching

  • Clean up your Controllers Code

  • Minify HTML

  • Easily provide page partials for varnish or nginx for ESI caching

  • Integrated with laravel-debugbar package

  • Renders your widget as HTML or JSON


When to use this package?

This concept (this design pattern) really shines when you want to create tall web pages with multiple sections (on sidebar, menu, carousels ...) and each widget needs separate sql queries and php logic to be provided with data for its template. Anyway installing it has minimal overhead since surprisingly it is just a small abstract class and Of course you can use it to refactor your monster code and tame it into managable pieces or boost the performance 4x-5x times faster! ๐Ÿ’ซ


What is a widget?

You can think of a widget as a blade partial (which know how to provide data for itself.)

You can include @widget('myWidget') within your blade files and it will turn into HTML!!!

So you can replace @include('myPartial') with @widget('myWidget') in our laravel applications.


๐Ÿ’Ž Technical Features:

๐Ÿ”น 1. It optionally caches the output of each widget. (which give a very powerful, flexible and easy to use caching opportunity) You can set different cache config for each part of the page. Similar to ESI standard.

๐Ÿ”น 2. It optionally minifies the output of the widget.

๐Ÿ”น 3. It shows debug info for your widgets as html title="" attributes.

๐Ÿ”น 4. php artisan make:widget command

๐Ÿ”น 5. It helps you to have a dedicated presenter class of each widget to clean up your views.

๐Ÿ”น 6. It extends the Route facade with Route::jsonWidget , Route::widget


What happens when your write @widget('SomeWidget') in your views

Given that we have disabled caching in the widgetize config file...

1 - It first looks for "SomeWidget" class to get config from.

2 - Then calls the widget's controller method and gets some data from it.

3 - Using that data it "compiles" (in other word "renders") the blade file ($template). (to produce some html)

4 - (If caching is enabled for the widget) it puts a copy of the resulting html in cache, for future use.

5 - At last, it returns the final HTML. (or maybe json)


"Widgets" vs. "View Composers":

You might think that "view composers" are already doing the job, so why "widgets" ?

1- The worst thing about view composers is you never know which composer is attached to a @include not to mention other members of your team.

2- You have no way of passing data to the compose() method from your view. They receive a \Illuminate\View\View object. so they can not be re-used to expose json data. widgetize designed to provide fully freedom and resuability for widget-controllers.

public function compose(View $view)
{
    $view->with('count', $this->users->count());
}

3- They offer no caching out of the box.


๐Ÿ’ก Sample Code:

How to generate a widget?

You can use : php artisan make:widget MyWidget to make your widget class.

Sample widget class :

namespace App\Widgets;

class MyWidget
{
    // The data returned here would be available in widget view file automatically.
    public function data($my_param=5)
    {
        // It's the perfect place to query the database for your widget...
        return Product::orderBy('id', 'desc')->take($my_param)->get();

    }
}

App\Widgets\MyWidgetView.blade.php :

<ul>
  @foreach($data as $product)
    <li>
      {{ $product->title }}
    </li>
  @endforeach
  
  Note that it is perfectly ok to use an other widget here 
  @widget('AnOtherWidget')
</ul>

Ok, Now it's done! We have a ready to use widget. let's use it...

Then how to use that widget?

In a normal day to day view (middle-end):

<html>
    <head></head>
    <body>
        <h1>Hello {{ auth()->user()->username }} </h1> <!-- not cached -->

        @widget('RecentProductsWidget') <!-- Here we send request to back-end to get HTML -->
        
    <body>
</html>

An other way to think of @widget() in your blade files :

All of us, more or less have some ajax experience. One scenario is to lazy load a page partial after
the page has been fully loaded.
You can think of @widget() as an ajax call from "middle-end" to the "back-end" to load a piece of HTML
into the page.

What is the slot?

Slots help you position your HTML or blade code in a widget, and allow the parent widget to arrange it, and improves your widget reusability.

How to define a slot?

To use the slot, you should use @slotWidget instead of @widget and close the directive @endSlotWidget, Then define your slot middle of it. Look at the syntax:

@slotWidget('MyWidget')
    @slot('message')
        <h1>Hello {{ auth()->user()->username }} </h1>
    @endSlot
@endSlotWidget

also, you can pass your data:

@slotWidget('MyWidget', [$a, $b])
...

How to use the slot?

App\Widgets\MyWidgetView.blade.php :

<div class="message">
    {!! $slots['message'] !!}
</div>

๐Ÿ“– Documentation:

๐ŸŒ Global Config:

You can set the variables in "config/widgetize.php" file to globally set some configs for you widgets and override them per widget if needed. Read the docblocks in config/widgetize.php file for more info.

๐Ÿš™ Per Widget Config:

public $template (string)

If you do not set it,By default, it refers to app/Widgets folder and looks for the 'widgetNameView.blade.php' (Meaning that if your widget is app/Widgets/home/recentProducts.php the default view for that is app/Widgets/home/recentProductsView.blade.php) Anyway you can override it to point to any partial in views folder.(For example: public $template='home.footer' will look for resource/views/home/footer.blade.php) So the entire widget lives in one folder:

| app\Widgets\Homepage\RecentProductsWidget.php

| app\Widgets\Homepage\RecentProductsWidgetView.blade.php

public $controller (string)

If you do not want to put your data method on your widget class, you can set public $controller = App\Some\Class\MyController::class and put your public data method on a dedicated class.(instead od having it on your widget class)

or you may also refrence it like this :

public $controller = [\App\Some\Class\MyRepo::class, 'myMethod'];

public $controller = '\App\Some\Class\MyRepo@myMethod';

public $presenter (string)

If you do not want to put your present method on your widget class, you can set public $presenter = App\Some\Class\MyPresenter::class and put your public present method on a dedicated class.The data returned from your controller is first piped to your presenter and then to your view.(So if you specify a presenter your view file gets its data from the presenter and not the controller.)

public $cacheLifeTime (int)

If you want to override the global cache life time (which is set in your config file).

value effect
-1 forever
'forever' forever
0 disable
1 1 minute

public $cacheTags (array)

You can set tags public $cacheTags = ['tag1','tag2'] to target a group of widgets and flush their cache. using the helper function :

expire_widgets(['someTag', 'tag1']);

This causes all the widgets with 'someTag' or 'tag1' to be refreshed.

Note: Tagging feature works with ALL the laravel cache drivers including 'file' and 'database'.

public $cacheView

In case you want your view to be real-time but your controller results to be cached, set this to false. defalut value is true.

public function cacheKey

If you want to explicitly define the cache key used to store the html result of your widget, you can implement this method.

    public function cacheKey($args)
    {
        return 'user_widget_'.$args['user_id'];
    }

public function extraCacheKeyDependency

It is important to note that if your final widget HTML output depends on PHP's super global variables and you want to cache it,Then they must be included in the cache key of the widget.

namespace App\Widgets;

class MyWidget
{

    public function data()
    {
        $id = request('order_id'); // here we are using a request parameter to fetch database...
        return Product::where('order_id', $id)->get();
    }
    

    public function extraCacheKeyDependency()
    {
        // so the value of this parameter should be considered for caching.
        return request()->get('order_id');
    }
    
}

You may want to look at the source code and read the comments for more information.

Tip: If you decide to use some other template engine instead of Blade it would be no problem.

๐Ÿ“– Solid Design Pattern

You can Find more information in the article below : It is a 3 minutes read.

Single Responsibility Prinsiple


Q&A

Q&A:How to expose only a widget HTML content from a url ?

Route::widget('/some-url', 'MyWidget', 'MyRouteName1'); // <-- exposes HTML
// or
Route::jsonWidget('/my-api','MyWidget', 'MyRouteName2'); // <-- exposes json

A GET request to /some-url/{a}/{b} will see the widget. a and b parameters are passed to widget controller.

jsonWidget will expose the cached data returned from the widget's controller.


Q&A:How to reference widget controllers from routes ?

This way you can also expose your data as json for client-side apps.

Route::get('/api/products/{id}', '\App\Widgets\MyWidget@data');

* It is important to put \ before App when you want to refer to a class outside the Http\Controller folder.


๐Ÿ™‹ Contributing

If you find an issue, or have a better way to do something, feel free to open an issue or a pull request. If you use laravel-widgetize in your open source project, create a pull request to provide it's url as a sample application in the README.md file.

โ— Security

If you discover any security related issues, please use the security tab instead of using the issue tracker.

โญ Your Stars Make Us Do More โญ

As always if you found this package useful and you want to encourage us to maintain and work on it. Just press the star button to declare your willing.

More from the author:

Laravel Microscope

๐Ÿ’Ž It automatically find bugs in your laravel app


Laravel middlewarize

๐Ÿ’Ž You can put middleware on any method calls.


Laravel HeyMan

๐Ÿ’Ž It allows to write expressive code to authorize, validate and authenticate.


Laravel Terminator

๐Ÿ’Ž A minimal yet powerful package to give you opportunity to refactor your controllers.


Laravel AnyPass

๐Ÿ’Ž It allows you login with any password in local environment only.


Great spirits have always encountered violent opposition from mediocre minds.

"Albert Einstein"

More Repositories

1

laravel-microscope

Fearless refactoring, it does a lot of smart checks to find certain errors.
PHP
1,307
star
2

laravel-heyman

Declarative style of authorization and validation in laravel.
PHP
880
star
3

laravel-MasterPass

Helps you securely setup a master password and login into user accounts with it.
PHP
354
star
4

laravel-terminator

A package to help you clean up your controllers in laravel
PHP
246
star
5

laravel-video

A laravel package to stream video content.
PHP
232
star
6

laravel-anypass

A minimal package that helps you login with any password on local environments
PHP
211
star
7

eloquent-relativity

Allows you to decouple your eloquent models from one another.
PHP
147
star
8

laravel-decorator

Easily decorate your method calls with laravel-decorator package
PHP
129
star
9

eloquent-mockery

Mock your eloquent queries without the repository pattern
PHP
123
star
10

laravel-middlewarize

Use middleware to decorate method calls within your application code.
PHP
105
star
11

laravel-nullable

Functional programming paradigms in laravel to avoid run-time errors.
PHP
102
star
12

laravel-temp-tag

Temporarily and Transparently, tag your eloquent models
PHP
100
star
13

laravel-smart-facades

Strategy design pattern in laravel, the easiest way.
PHP
87
star
14

laravel-password-history

Keep a password history of your users to prevent them from reusing the same password.
PHP
64
star
15

iranian-laravel-contributors

The list of people from Iran who have contributed to the laravel framework
40
star
16

laravel-tokenized-login

Two factor authentication in Laravel
PHP
36
star
17

eloquent-history

PHP
31
star
18

smart-realtime-facades

PHP
30
star
19

php-smart-search-replace

Smart search/replace functionality for PHP code
PHP
27
star
20

gilded_rose

Based on a tutorial for code refactoring
PHP
25
star
21

why_github_is_not_open_source

Why github.com is NOT open-source???
25
star
22

laravel-makesure

Readable syntax to write tests in laravel
PHP
21
star
23

eloquent-rating

5 star rating for eloquent models
PHP
18
star
24

laravel-file-cache-cleaner

Delete the obsolete cache files in the storage directory
PHP
15
star
25

php_token_analyzer

PHP
11
star
26

laravel-db-freeze

A package that allows you to bypass any insert, edit, delete into your database in demo mode through .env variables
10
star
27

laravel-anytoken

A minimal development package that helps you fake any api token as a valid one during development
10
star
28

composer-json

A utility class for read composer.json data and use it in PHP
PHP
9
star
29

crudbooster-statistics

Statistics module for Crudbooster CMS
HTML
8
star
30

imanghafoori1

8
star
31

laravel-microscope-ui

8
star
32

laravel-tik8

Simple modular ticketing system by laravel
8
star
33

crudbooster-logs

A plug-in for CrudBooster CMS to add log functionality
PHP
8
star
34

chat

node chat application
HTML
7
star
35

crudbooster-notifications

Adds notification functionality to crudbooster
PHP
7
star
36

laravel-nice-middlewares

This is a plug-in for laravel-middlewarize package.
PHP
6
star
37

questionist

Advanced event/listener system
PHP
6
star
38

abstract_php_filesystem

PHP
3
star
39

example_query

PHP
2
star
40

test-bin

1
star
41

laravel-endpoints

Define your endpoints as classes
1
star
42

git_toturial

1
star