Let a Package use the ServiceProvider of a "master"package in Laravel - 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.

Related

Is it possible to have submodules in Laravel?

There are several web services that support multiple android applications written in Laravel. Each web service contains multiple modules. The board of directors decided to move all of the web services into one Laravel installation as modules. So the webServer1 which is an independent web service will have to be a module of the collection of web services integrated in to one Laravel installation.
Because some web services are big enough to have modules and they are implemented by nwidart package, I have to implement it as what it is in this new integration. So the only way to implement it is to be able to have submodules.
I would like to know does nwidart support such thing? and how can I do this?
Besides that, is it in general, a good idea to to such thing? May be I can dissuade the he board of directors :)
Thanks.
You can do it using composer like for example
"psr-4": {
"App\\": "app/",
"SubModule\\": "SubModule/Path"
}
Then create a service provider
inside your module like
<?php
namespace Your\Directory\Here;
use Illuminate\Support\ServiceProvider;
class CustomServiceProvider extends ServiceProvider
{
protected $defer = true;
/**
* Bootstrap the application events.
*
* #return void
*/
public function boot()
{
$this->loadViewsFrom(__DIR__ . '/resources/views', 'YOuCanNameHereAnyThing');
}
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
$this->mergeConfigFrom(__DIR__ . '/config/config.php', 'config');
}
}
You don't need any third party package to make a Laravel application modular, and I'd argue that doing so introduces an unnecessary dependency. Composer allows you to autoload any folder you want under a particular namespace via PSR4 autoloading.
Sometimes it may also make sense to put some code in different packages and pull them in when required using Composer. It's possible to use any VCS repository as a source for a package, so your modules can be in a private repository if necessary.
Making your code more modular in general is a good idea because it allows for code reuse. For instance, if you built some functionality that would be useful on other projects, you can place it in a package by itself and require it with Composer.

Lumen/Laravel - use custom router

Is there any out of the box solution without changing core to add custom router in to laravel or lumen. I already know that lumen is using different router from laravel, so I am wondering is there any possibility builded in core to change router?
I had the same question today. After some research I found a solution which will impact the core classes minimal.
Note: The following description is based on Lumen 6.2.
Before you start; think about a proper solution, using a middleware.
Because of the nature of this framework, there is no way to use a custom Router without extending core classes and modifying the bootstrap.
Follow these steps to your custom Router:
Hacky solution
1. Create your custom Router.
Hint: In this example App will be the root namespace of the Lumen project.
<?php
namespace App\Routing;
class Router extends \Laravel\Lumen\Routing\Router
{
public function __construct($app)
{
dd('This is my custom router!');
parent::__construct($app);
}
}
There is no Interface or similar, so you have to extend the existing Router. In this case, just a constructor containing a dd() to demonstrate, if the new Routerist going to be used.
2. Extend the Application
The regular Router will be initialized without any bindings or depentency injection in a method call inside of Application::__construct. Therefore you cannot overwirte the class binding for it. We have to modify this initialization proccess. Luckily Lumen is using a method just for the router initialization.
<?php
namespace App;
use App\Routing\Router;
class Application extends \Laravel\Lumen\Application
{
public function bootstrapRouter()
{
$this->router = new Router($this);
}
}
3. Tell Lumen to use our Application
The instance of Applicationis created relativley close at the top of our bootstrap/app.php.
Find the code block looking like
$app = new Laravel\Lumen\Application(
dirname(__DIR__)
);
and change it to
$app = new App\Application(
dirname(__DIR__)
);
Proper solution
The $router property of Application is a public property. You can simply assign an instance of your custom Router to it.
After the instantiation of Application in your bootstrap/app.php place a
$app->router = new \App\Routing\Router;
done.

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...
}
}

Laravel 5 binding other object to contracts

I started using Laravel 5 and tried to learn things about contracts but i still have some questions about them.
For example I want to alter the Illuminate\Contracts\Auth\PasswordBroker contract (used in App\Http\Controllers\Auth\PasswordController )
The contract is an Interface but somehow Laravel knows what implementation belongs to that contract..
I want to change the implementation to my custom one.
But what is the correct way of loading my custom PasswordBroker class?
Should i bind my custom class in the AppServiceProvider?
$this->app->bind(
'Illuminate\Contracts\Auth\PasswordBroker',
'App\Services\MyPasswordBroker'
);
Where does Laravel itself bind the default implementations?
It's in 'Illuminate/Foundation/Application.php'
'auth.password' => ['Illuminate\Auth\Passwords\PasswordBroker', 'Illuminate\Contracts\Auth\PasswordBroker'],
Can I just overwrite the default bindings?
According to the official documentations: Yes.
You can easily extend and override this class within your own application by overriding this binding.
But remember to replace the original service provider in the config/app.php
Note that this class extends the HashServiceProvider, not the default ServiceProvider base class. Once you have extended the service provider, swap out the HashServiceProvider in your config/app.php configuration file with the name of your extended provider.
Your case
So, in your case, you need to extend the 'Illuminate\Auth\Passwords\PasswordResetServiceProvider' to remain other things happened in the service provider.
Take a look at the default service provider.
Let me know if you have other questions.

Laravel 4 - when to use service providers?

I tried to google it but did not find detailed information.
Service providers are a great way to group related IoC registrations
in a single location. Think of them as a way to bootstrap components
in your application.
Not understanding from the documentation. Is this only needed when I create packages? So when I am regular developer and not making some packages to release in public - I don't need to care?
One of the keys to building a well architected Laravel application is
learning to use serviceproviders as an organizational tool. When you are
registering many classes with the IoC container, all of those bindings
can start to clutter your app/start files. Instead of doing container
registrations in those files, create serviceproviders that register
related services.
So, this is a way to organize your application's services in one place to keep it more organized. A service provider must have at least one method: register. The register method is where the provider binds classes to the container. When a request enters your application and the framework is booting up, the register method is called on the providers listed in your configuration file
'providers' => array(
'Illuminate\Foundation\Providers\ArtisanServiceProvider',
'Illuminate\Auth\AuthServiceProvider',
'Illuminate\Cache\CacheServiceProvider',
// more ...
'Illuminate\Html\HtmlServiceProvider',
// more ...
)
This is providers array in app.php config file and this is the HtmlServiceProvider stored in 'Illuminate\Html\HtmlServiceProvider.php'
use Illuminate\Support\ServiceProvider;
class HtmlServiceProvider extends ServiceProvider {
//...
public function register()
{
$this->registerHtmlBuilder();
$this->registerFormBuilder();
}
protected function registerHtmlBuilder()
{
$this->app['html'] = $this->app->share(function($app)
{
return new HtmlBuilder($app['url']);
});
}
protected function registerFormBuilder()
{
$this->app['form'] = $this->app->share(function($app)
{
$form = new FormBuilder($app['html'], $app['url'], $app['session']->getToken());
return $form->setSessionStore($app['session']);
});
}
}
When, Laravel boots up, it calls this (register) method and in this method there are two lines, these line calls two methods, registerHtmlBuilder() and registerFormBuilder(), these both methods components to the IoC container using
$this->app['html'] = $this->app->share(...);
$this->app['form'] = $this->app->share(...);
In this case both are anonymous functions which returns an instance of html/form class and that's why, when you use
Html::link(...);
Or, using form
Form::input(...);
You get the bound class from the $app object which is available to your application. In this case 'Html' => 'Illuminate\Support\Facades\Html', is used to alias the main class in the aliases array in the app.php file.
So, in Laravel, service providers are a way to organize things in a nice cleaner way, during the boot up process of your application, Laravel runs all register methods from all the service providers so each component become available (bound) to the IoC container so you can access them in your application.
It's worth mentioning that, after calling of all register methods from service providers all the boot methods from those service providers get called. In that case, if you need to use any service from the application (IoC/Service Container) within the service provider class then you should use that service from the boot method since it's not guranteed that any service is avaiable during the registeration of service providers (within register method) because services are registered through register method of each service provider but within the boot method you may use any service because by then every service is hopefully registered.
Check this answer Laravel 4 : How are Facades resolved? too, it may help you to understand.
There's nothing a service provider can do that you can't just slap into app/start/global.php, but with a service provider you gather all the logic in one place and can develop application in a more modular fashion.
If you're making a package a service provider is pretty much a must.
In Laravel, service providers are directly related to the way in which IoC container works. They allow easier and more modular approach to dependencies. In fact, it is a great pattern for organizing your code in a bootstrap fashion ( even outside of Laravel ). I think If you are regular developer you still need to know the basics of Laravel service providers, because that pattern is integral part of Laravel architecture. I am sure it can make your work easier.
For example, when installing a package, your have to give application access to that package - one of the best solution is through service providers list and a facade. On the other hand, I can't imagine being a Laravel developer without knowing basics of SP-s.

Resources