Why create a facade in laravel instead of calling a method directly? - php

I'm just starting with laravel and want to understand this...
Lets say we have a class in our application:
namespace App\Tests;
class MyTest{
public function sayHello($name){
echo "Hello, $name!";
}
public static function anotherTest(){
echo "another test...";
}
}
What is the advantage of creating a facade and a service provider over just using it as
use App\Tests\MyTest;
//... controller declarations here ....
public function someaction(){
$mt = new MyTest();
$mt->sayHello('John');
//or
MyTest::anotherTest();
}
//... etc...

A Facade in Laravel is only a convenient way to get an object from the Service Container and call a method on it.
So calling a Facade like this :
//access session using a Facade
$value = Session::get('key');
Is like doing:
//access session directly from the Service Container
$value = $app->make('session')->get('key');
As the Facade resolves the session key out of the Service Container and call the method get on it
Once understood what a Facade does, you should understand what is the Service container and what are the benefits of using it
The Service Container in Laravel cloud be a Dependency Injection Container and a Registry for the application
The advantages of using a Service Container over creating manually your objects are stated in one of my previous answers and in the doc page, but briefly:
Capacity to manage class dependencies on object instantation
Binding of interfaces to concrete classes, so that when a interface is requested in your program, a concrete class is instantiated automatically by the service container. Changing the concrete class on the binding, will change the concrete objects instantiated through all your app
Possibility to create single intances and get them back later (Singleton)

Related

Laravel service class can work even without service provider?

When implementing a service, base on Laravel's documentation, a service should be registered on the service provider so it could be injected into a class via dependency injection. But I do notice that even though I do not create a service provider as such, I could still inject that class.
If so, what's the use of the service provider class if I could just directly inject it?
Here's some sample:
use App\Http\Service\MailerService;
class MailerServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton(MailerService::class, function($app) {
return new MailerService();
});
}
}
class MailerService
{
public function send()
{
// do something here
}
}
class MailerController
{
public function sendEmail(MailerService $mailerService)
{
$mailerService->send();
}
}
Good question!
Laravel's Container has the ability to "auto-resolve" dependencies. If you ask the Container to create an instance of a class and there is no specific binding definition for the class, the Container will attempt to find the class, use PHP's Reflection functionality to check its dependencies, and recursively build the dependency tree until it's finished or runs into a problem.
The use-cases and benefits of using a Service Provider even with this capability:
You want to bind an Interface to the container, and have it resolved to a concrete class. Interfaces can't be instantiated directly, so you have to tell the container what concrete class to use.
Your binding has a non-class dependency, such as a string config value. These can't be auto-resolved.
Auto-wiring is slow. It has to use Reflection for every class that doesn't have a service provider binding.
You want to include some sort of logic in the resolution process.
Might be a couple other use cases or benefits I'm forgetting, but those should be a good start!

Lumen (Laravel) include library & use class in Controller

I have a question! I have a library, whenever I need to call, I'll include it into & new Class() like the link below.
Now, I want to include it to use with Lumen framework & call usually inton Controller, then how to register service, class in Lumen to make it comfortable so that when needing, just call new FileMaker();
http://laravel.io/bin/E3d9x
Thank you so much!
What you're looking for is a Service Provider. Instead of including files in your Controllers, and then new'ing up instances of a class it is better to register the class within a service provider and then resolve the object out of the IoC container.
An example of how you can register a provider:
public function register()
{
$this->app->singleton('Full\Vendor\Namespace\FileMaker', function($app) {
return new FileMaker('someparameters');
});
}
Doing it this way means that you can inject dependencies into your Controllers and Laravel, or Lumen in this case will automatically resolve the object without you needing to instantiate the object.
For example, in your controller:
public function someControllerMethod(FileMaker $filemaker)
{
// The $filemaker instance is available to use
}

Trouble Understanding Facade in Laravel

For the most part I get the idea behind a facade and how the details of instantiating the object are hidden behind the static calls.
So if we take a look at this straight forward example here: Example
We see some code like this for the facade, which at this point just sets up some sort of Alias. At this point it seems the facade still knows nothing about the Superuser class.
class SuperuserFacade extends Facade
{
protected static function getFacadeAccessor() {
return 'MyAlias';
}
}
The logic is glued by the service provider here it seems:
class SuperuserServiceProvider extends ServiceProvider
{
public function register() {
App::bind('MyAlias', function(){
return new Superuser;
});
}
}
But it just binds the class the facade alias MyAlias. Why bother with that facade class and two separate files, can't we just do all this logic right in the service provider? Or alternatively in the facade provider having it just return the Superuser class?
It seems like we have the facade not really doing anything and then another file telling that facade what to do. Why have these concerns been separated?
The facade class is a simple proxy -- it directs any calls to the facade class to the root class, which is retrieved from the IoC container via the facade accessor (in this case, MyAlias).
I call Superuser::whoami()
The Superuser facade goes "okay, I need to find the class that I'm a proxy for."
The facade calls getFacadeAccessor() to determine what IoC binding to retrieve and subsequently call.
The facade requests the MyAlias key from the IoC container. The container then returns an existing class if it has been built already, or it runs its bound closure which generates a new Superuser instance.
Now that the facade knows what class it's passing calls to, it forwards the whoami() method call to the newly-returned Superuser instance, which then returns whatever it is designed to.
The service provider's register() method simply registers a binding to the IoC container, to be retrieved later by whatever needs it. That's it. MyAlias is a simple string key used to look up that binding.
The facade allows you to use an IoC-bound class as if it were a static class.
I recommend reading other articles about the concept, because the article you linked is both inaccurate and not very informational about why things work. Here is a better article by Chris Fidao.

PHP Dependency Injector or Factory?

I'm using Zend Framework 1 and Pimple dependency injector. After watching some Google Guice presentations on YouTube, I'm not sure if I'm really using DI and not a simple factory. The way I'm making use of my Pimple injector is by asking it to give me an instance of some object based on a string key registered and associated with the object:
class SomeService extends AbstactService {
/** #var Pimple $injector Inherited from base class */
protected $injector;
public function save(array $data) {
$model = $this->injector["some-model"];
if (empty($data["id"])) {
$model->insert($data);
} else {
$model->update($data);
}
}
}
The member variable $injector is created and configured at bootstrap, and sent to my AbstractService class, so all concrete services inherit it.
So by the way that $injector is used here, even though it uses Pimple (a DI container), is this implementing DI pattern or something else (factory or maybe service locator) ?
Update
Some further info: I'm using Zend Framework (MVC) building a nutrition/exercise website.
I think what is confusing me is how to create some object inside a method, where that object is only needed for that method, and the method takes some run-time arguments. For example, the SomeService class gets instantiated by the container in my controller. Then I call SomeService::save() passing in $data. Where and how would $model be created? Suppose $model is only used in that particular method, so that it wouldn't make sense to make it a class member, how could that be injected by the container?

How does laravels IoC/Dependency Injector intsantiate to static instances?

So this is probably a rather simple question but I can't seems to find a very direct answer. I supposed to could keep reading the source until i figure it out but I was hoping to get a bit of understand of the process of doing so.
I understand IoC and Dependency injection, I am certainly not very experienced in either but I have a good understand of what they are trying to accomplish. So how does this Laravel instantiate to static instances? I know it uses PHP reflections but I'm still lost on the part of going from non-static to static methods. Also I know Laravel is not the only framework to implement such a design but its my preferred and most understood framework.
When you call a static method on a facade it is being handled by the magic __callStatic method on the Facade class. This method gets the underlying class that serves the facade and proxies the static call to it.
Let's look at an example facade:
<?php
class MyFacade extends Facade {
public function getFacadeAccessor() { return "MyFacade"; }
}
With this example when we make a call to the class in a static manner such as: MyFacade::doSomething() no static method exists on the class. The underlying Facade base class however contains a __callStatic method that will be called.
Facade Class Source Code
public static function __callStatic($method, $args)
{
$instance = static::resolveFacadeInstance(static::getFacadeAccessor());
switch (count($args))
{
case 0:
return $instance->$method();
// Snipped for brevity...
This method then looks up the underlying class to service the facade. If the getFacadeAccessor method on the facade returns a string then a matching entry in the application's IOC container is used (i.e. $app['MyFacade']). If we returned an object from the getFacadeAccessor method it would be used instead (i.e. public function getFacadeAccessor(){ return new MyClass(); }
Turns out that Laravel instantiate the classes under the hood! In this site, the guy makes you understanding a little more of the Laravel's core by using it to create a new facade. In the way, he explains how tit works!
It quite simple, actualy:
1 - You create a classe which extends from Laravel's Facade class with a single call like:
<?php namespace Name\Space;
use Illuminate\Support\Facades\Facade;
class MyClass extends Facade {
/**
* Get the registered name of the component.
*
* #return string
*/
protected static function getFacadeAccessor() { return 'myclass'; }
}
... that's make Laravel look for $app['myclass']. So, the ServiceProvider will bind the myclass to MyClass (according to Laravel's conventions).
2 - For that, of course, you'll have to create a Service Provider.
The Service Provider will be responsible for returning the namespace, in this case Name\Space, for the class(es) that you may want to 'turn into facades'.
3 - You'll have to register your Service Provider in the providers array in the app/config/app.php.
Now, if you look with more attention, you'll realise that what Laravel does is just import a namespace and understanding it as it was a class, as well. Under the hood, it will call a instance, but for user (programmer) it will looks like a static call.
I hope I had been clear about it! Look the link I gave to you up there and HAVE FUN! :D

Categories