Confused - AppServiceProvider.php versus app.php - laravel

Where do I specify my bindings exactly? It seems I can do it in either of these files.
config/app.php
Inside of 'providers' =>
app/Providers/AppServiceProvider.php
Inside of register()

The service providers array is loaded via config/app.php. This is the only actual place that providers are registered, and is where you should put Service Providers.
AppServiceProvider is for Laravel-specific services that you've overridden (or actually specified), such as the Illuminate\Contracts\Auth\Registrar, The HTTP/Console Kernels, and anything you wish to override in Laravel. This is a single service provider, that registers container bindings that you specify.
Really, you could load anything you want here, but there's a bunch of ready-to-go service providers in the app/Providers directory for you so you don't have to go and make one yourself.

If your bindings are not related to App, then I would create a new ServiceProvider class where I overwrite the register method with my new binding, then you have to let Laravel know that this class exists registering as a Provider in your config/app.php providers list, that is:
app/Providers/MyNewClassServiceProvider.php
<?php namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class MyNewClassServiceProvider extends ServiceProvider {
public function register()
{
$this->app->bind(
'App\Repository\MyNewClassInterface',
'App\Repository\MyNewClassRepository'
);
}
}
config/app.php
'providers' => [
// Other Service Providers
'App\Providers\MyNewClassServiceProvider',
],

Related

How can I include php file in Lumen/Laravel AppServiceProvider register function?

When I tried to custom polymorphic types in a morph relationship, as the spec recommended,
You may register the morphMap in the boot function of your
AppServiceProvider or create a separate service provider if you wish.
I added the morpMap function in AppServiceProvider register function (I don't find the boot function in Lumen 5.3 which is used).
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$propertyConfig = include ('../config/config_property.php');
Relation::morphMap($propertyConfig['property_morph_map']);
}
}
Then, when I tried to run some php artisan commands, it threw this error,
[ErrorException]
include(../config/config_property.php): failed to open stream: No such
file or directory
but the morphMap function does work, which means the address is correct when I run this code on Homestead.
This is my first Lumen project, and I'm still not familiar with the Service Provider. It's kind of weird to me how the register function can influence the artisan command...
You can load the configure file in bootstrap/app.php through below code.
$app->configure('config_property')
To use the configure file in AppServiceProvider use configure().
Here is the code.
Relation::morphMap(configure('config_property.property_morph_map'));

register serviceprovider at runtime instead of app.php

Is it possible to register serviceprovider at runtime instead of having it preregistered in app.php providers list? If yes how would it be done? Could I register it from some other service provider that is aready in app.php and running?
its possible to register a service provider at any time by calling the register method on the ioc container...
Using the facade:
App::register($yourProvider);
Using the helper:
app()->register($yourProvider);

Let a Package use the ServiceProvider of a "master"package in Laravel

I want to develop some packages for Laravel. So I want to create a "master" package fitting the Laravel-package-development guidelines as written on Laravel.com. Then I want to extend this package with other packages (or let other developers extend it).
Because of this, I want to make it as easy as possible for me/them. So I am looking for a way to register these sub-packages without the need of registering them in the config/app.php.
It would be great if these sub-packages could be registered and activated through the master-package, which is correctly registered via ServiceProvider, ClassAlias and Facade. Or is there a way to register them automatically in config/app.php?
I found a package on GitHub caffeinated/modules, which provides something like this, but there it's not possible to install and update new packages via composer.
It would be great, if one of you could help me with this problem, because I want to make it as easy as possible to extend the master-package.
Thanks!
You don't need caffeinated/modules, Laravel supports registering modules with all of their components out of the box, so this package is unnecessary.
What I usually do for my modules is - I have a main provider that registers the other providers of the other modules:
class MainModuleServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->register( FirstModuleServiceProvider::class );
$this->app->register( SecondModuleServiceProvider::class );
}
}
And in each of these providers I register providers for the module views, routes, etc.:
class FirstModuleServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->register( RouteServiceProvider::class );
$this->app->register( ViewServiceProvider::class );
}
}
In these providers I load the views, routes and publish the migrations as described in the Laravel doc.

How to integrate in Laravel 5 a Package from Packagist?

I'm working with laravel 5 and trying to integrate the following package:
exacttarget/fuel-sdk-php
I executed on my project:
composer require exacttarget/fuel-sdk-php
So I had on my vendor dir exacttarget provider.
First thing I've noticed this particular package doesn't use namespaces, so it still calls require directives but not "use \path\namespace"
Is it a right approach? I haven't seen many packages yet but among my past experience doesn't look to me the right approach to write a package...
After this I edit condif/app.php to use ET_Client class.
'providers' => [
...
'ET_Client',
...
],
Once I did this, I got an error: looks like Laravel frmwk tries to instantiate the class, that needs some parameters to work, even if I'm not yet using it (istantiating). It this a normal behavior from Laravel?
Am I missing something ?
The providers array is for registering service provider classes. Unless ET_Client extends Laravel’s base ServiceProvider class, it’s not going to work.
Instead, just add the use statements to your PHP classes as and when you need to use the class:
<?php
namespace App\Http\Controllers;
use ET_Client;
class SomeController extends Controller
{
public function someAction()
{
// Instantiate client class
$client = new ET_Client;
// Now do something with it...
}
}

Dynamic paths for laravel 5

While building multi-tenancy packages for Laravel 5 I had to find out how to make the paths and namespaces dynamic.
This would involve:
views; adding a template directory dynamically that is available in the root namespace
lang; adding a language directory dynamically that is available in the root namespace
routes; adding a routes file dynamically
config; merging additional configuration files from a dynamic location
vendor; allowing custom vendors and packages to be available from a dynamic location
views
Using a service provider you can use the following in your boot() method for views to be available in the root namespace (view('your-view') instead of view('package::your-view')):
$this->app['view']->addLocation('/your/new/location');
lang
Using a service provider you can use the following in your boot() method where $path is the new path for your root namespace translations:
$app->bindShared('translation.loader', function($app) use ($path)
{
return new \Illuminate\Translation\FileLoader($app['files'], $path);
});
$app->bindShared('translator', function($app)
{
$translator = new \Illuminate\Translation\Translator($app['translation.loader'], $app['config']['app.locale']);
$translator->setFallback($app['config']['app.fallback_locale']);
return $translator;
});
routes
Routes is by far the easiest. Simply include them using a require_once or by using the Laravel method: \File::requireOnce().
config
I used a directory that would allow a tenant to overrule core configs. Please advice there are no security nor sanity checks here so access should be limited.
Using a service provider you can use the following in your boot() method
foreach (\File::allFiles('/path/to/configs') as $path) {
$key = \File::name($path);
$app['config']->set($key, array_merge(require $path, $app['config']->get($key, [])));
}
This will merge existing configurations by overruling their values with the provided config files.
vendor
Really interesting is the possibility to use dynamically loaded classes. In order to do this you will need to use the ClassLoader addDirectories() method in your service provider
\Illuminate\Support\ClassLoader::addDirectories(['/path/to/vendors']);
additional considerations
The above code can be implemented using service providers. In order for a server provider to work you must add them to the config/app.php file under the providers array. Not doing so will not enable any of the code in the service provider.

Resources