Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel facade __constructor() usage

Tags:

php

laravel

I have made a class. The class's constructor assigns a value to a class property.

Here is the definition:

class myClass 
{
    private $_value;

    function __construct ($input)
    {
        $this->_value = $input;
    }

    function echoThat ()
    {
        echo $this->_value;
    }
}

And the regular usage is:

$x = new myClass("SimpleString");
$x->echoThat();

But I have turned the class into a facade type of class in Laravel so it is used:

myClass::echoThat();

How should I utilize the __construct() method in Laravel Facades like the above example?

like image 547
Mostafa Talebi Avatar asked Sep 03 '25 01:09

Mostafa Talebi


2 Answers

You should only create a Laravel facade if you really want to use your class like Laravel facades are used. Laravel facades provide a static interface to a class.

This means either rewrite your class so that you can pass your string in anyother way like:

MyClassFacade::echoThat('SimpleString');

Of course you can also modify the underlying class to use for example another method to pass the string:

class MyClass 
{
    private $_value;

    public function setValue($val) 
    {
        $this->_value = $val;

        return $this;
    }

    public function echoThat()
    {
        echo $this->_value;
    }
}

And then call it like:

MyClassFacade::setValue('SimpleString')->echoThat();

You can call the non static methods of you class "statically" if you instantiate your class wherever the Laravel facade accessor is resolved, for example in the service provider:

use Illuminate\Support\ServiceProvider;

class MyClassServiceProvider extends ServiceProvider 
{
    public function register()
    {
        $this->app->bind('myclass', function()
        {
            return new MyClass();
        });
    }

} 

Laravel will create an instance of MyClass whenever a method on your class is called statically using __callStatic.

Or don't use the Laravel facade and instantiate your class manually like you did it:

$x = new myClass("SimpleString");
$x->echoThat(); 
like image 116
Marcel Gwerder Avatar answered Sep 05 '25 06:09

Marcel Gwerder


You have first to understand that a Facade, in Laravel, is not really your class, you must look at it, as the name says, a forefront or a frontage to your class. Facade is, acually, a Service Locator to your class.

To use this Service Locator you have to create a Service Provider, which will provide the service used by the Facade:

<?php namespace App\MyApp;

use Illuminate\Support\ServiceProvider;

class MyClassServiceProvider extends ServiceProvider {

    protected $defer = true;

    public function register()
    {
        $this->app['myclass'] = $this->app->share(function() 
        { 
            return new MyClass('the values you need it to instantiate with');
        });
    }

    public function provides()
    {
        return array('myclass');
    }

}

Note that your class is instantiated in the method register() and now is available to your application via the IoC container, so you can do things like:

App::make('myclass')->echoThat();

And now you can also create your Facade to use it:

<?php namespace App\MyApp;

use Illuminate\Support\Facades\Facade as IlluminateFacade;

class ExtendedRouteFacade extends IlluminateFacade {

    protected static function getFacadeAccessor() 
    { 
        return 'myclass'; 
    }

}

The Facade has only one method and its only purpose is to return the name of your class instance in the IoC container.

Now you can open your app/config/app.php and add the ServiceProvider:

'App\MyApp\MyClassServiceProvider',

also the actual Facade alias:

'MyClass' => 'App\MyApp\MyClassFacade',

and you should be good to use your Facade:

echo MyClass::echoThat();

But note that the way it is made your class __constructor will be always called with the same parameters, in your ServiceProvider, that's how a Facade works, but you have some options:

Use a setter to set a new value for the data in your class instance.

public function setValue($value)
{
    $this->_value = $value;
}

Use the Laravel automatic class resolution to provide parameters for your class dinamically:

function __construct (MyFooClass $foo)
{
     $this->_foo = $foo;
}

And alter your ServiceProvider to provide no parameters to your class:

$this->app['myclass'] = $this->app->share(function() 
{ 
    return new MyClass();
});

Laravel will instantiante MyFooClass automatically for you, if it can locate it in the available source code of your application or if it's bound to the IoC container.

Note that all this assumes that you're not just passing a string in your constructor, the automatic resolution of the IoC container assumes your class has other class dependencies and inject those dependencies automatically (Dependency Injection).

If you really need to just pass strings or single values to constructors of classes that just do some calculations, you don't really need to create Facades for them, you can just:

$x = (new myClass("SimpleString"))->echoThat();

using a simple setter:

$x = new myClass();
$x->setValue("SimpleString");
$x->echoThat();

or, as you were already doing, which is acceptable:

$x = new myClass("SimpleString");
$x->echoThat();

And you can also use the IoC container to instantiate that class for you inside your other classes:

<?php

class Post {

    private $myClass;

    public function __construct(MyClass $myClass)
    {
        $this->myClass = $myClass;
    }

    public function doWhateverAction($value)
    {
        $this->myClass->setValue($value);

        // Do some stuff...

        return $this->myClass->echoThat();
    }

}

Laravel will automatically pass an instance of your class and you can use it the way you need:

$post = new Post;

echo $post->doWhateverAction("SimpleString");
like image 24
Antonio Carlos Ribeiro Avatar answered Sep 05 '25 06:09

Antonio Carlos Ribeiro