ArtisanTinkerer.github.io

Blog

View on GitHub

Package Development

A Note of Facades

When writing a package you will not have access to Laravel’s testing helpers. If you would like to be able to write your package tests as if you are using Laravel you may use Orchestral Testbench

https://github.com/orchestral/testbench

What is a Facade

https://www.sitepoint.com/how-laravel-facades-work-and-how-to-use-them-elsewhere/

A facade is a class, wrapping a complex library to provide a simpler more readable interface.

missing

Facades in Laravel

A class which provides static-like interfaces to service inside the container.

In Laravel, all services have a facade class.

Package Discovery

app.php providers option is a list of service providers what should be loaded. When someone installs your package you want your service provider to be included in this list. This can be done in the extra section of your package’s composer.json file. You may also list any facades which you would like registered.

Service Providers

Are the connection points between your package and Laravel. A service provider is responsible for binding things into Laravel’s Service Container and informing Laravel where to load package resources susch as views, configuration and localization files.

They extend Illuminate\Support\ServiceProvider and contain register and boot.

Resources

Configuration

Get copied with vendor:publish

public function boot()
{
    $this->publishes([
        __DIR__.'/path/to/config/courier.php' => config_path('courier.php'),
    ]);
}

Routes

public function boot()
{
    $this->loadRoutesFrom(__DIR__.'/routes.php');
}

Migrations

public function boot()
{
    $this->loadMigrationsFrom(__DIR__.'/path/to/migrations');
}

Views

$this->loadViewsFrom(__DIR__.'/path/to/views', 'courier');

Commands

Public Assets

The Service Container

https://laravel.com/docs/5.6/container

Introduction

For managing class depencies and performing dependency injection.

public function __construct(UserRepository $users)

Bindings

Simple Bindings

$this->app->bind('HelpSpot\API', function ($app) {
    return new HelpSpot\API($app->make('HttpClient'));
});

Binding a Singleton

$this->app->singleton('HelpSpot\API', function ($app) {
    return new HelpSpot\API($app->make('HttpClient'));
});

Once a singleton is created, the same object will be returned on subsequent calls.

Binding Instances

$api = new HelpSpot\API(new HttpClient);

$this->app->instance('HelpSpot\API', $api);

Binding Primitives

$this->app->when('App\Http\Controllers\UserController')
          ->needs('$variableName')
          ->give($value);

Binding Interfaces To Implementations

$this->app->bind(
    'App\Contracts\EventPusher',
    'App\Services\RedisEventPusher'
);

Contextual Binding

Two classes from same interface. Just add two different bindings.

$this->app->when(PhotoController::class)
          ->needs(Filesystem::class)
          ->give(function () {
              return Storage::disk('local');
          });

Tagging

$this->app->bind('MemoryReport', function () {
    //
});

$this->app->tag(['SpeedReport', 'MemoryReport'], 'reports');

You can then bind the tagged ones:

$this->app->bind('ReportAggregator', function ($app) {
    return new ReportAggregator($app->tagged('reports'));
});

Resolving

Using Make

$api = $this->app->make('HelpSpot\API');
//or
$api = resolve('HelpSpot\API');

Automatic Injection

 public function __construct(UserRepository $users)

Container Events

$this->app->resolving(function ($object, $app) {
    // Called when container resolves object of any type...
});

Service Providers

https://laravel.com/docs/5.6/providers

Service providers are where things are registered: container bindings, event listeners, middleware and routes. php artisan make:provider RiakServiceProvider

Writing Service Providers

only bind things into the service container ** **never attempt to register any event, routes etc within the register method (you may accidentally use a service that is provided by a service provider which has not loaded yet.)

All have a register and boot method.

Register

Only bind things into the Service Container

define an implementation of Riak\Connection in the service container

public function register()
    {
        $this->app->singleton(Connection::class, function ($app) {
            return new Connection(config('riak'));
        });
    }

When to use a service provider?

From https://laracasts.com/lessons/service-providers-decoded

** IOC container is the application **

Can bind, useful when you have dependencies:

$filesystem = new Illuminate\Filesystem\Filesystem(new Foo, new Bar(new Baz));

This is cumbersome. Can be done once in a service provider:

public function register()
{
    $this->app->bindShared('files', function() {return new Filesystem(new Baz, new Bar, new Foo)});
}

This will enable us to do this:

$filesystem = $app['files'];

Quick example

Foo needs Bar and Baz:

Instead of:

$foo = new Foo( new Bar, new Baz)

Can use:

App::bind('Foo', function()
{
    return new Foo(new Bar, new Baz)
} );

dd(App::make('Foo'))

The app binding can then go in a service provider.

This is all just about resolving depencies.

Imagine you have created a class which requires multiple dependencies and in general you use it like this:

$foo = new Foo(new Bar(config('some_secret_key')), new Baz(new Moo(), new Boo()), new Woo('yolo', 5));

it’s doable, but you wouldn’t want to figure out these dependencies every time you try to instantiate this class. That’s why you want to use service provider where in the register method you can define this class as:


$this->app->singleton('My\Awesome\Foo', function ($app) {
   return new Foo(new Bar(config('some_secret_key')), new Baz(new Moo(), new Boo()), new Woo('yolo', 5));
});