I have a class called Messaging and I created a facade to using it like
Messaging::getConversationMessages($conv_id, $user_id);
I have followed all the instructions in this link below
How do I create a facade class with Laravel?
This is my MessagingServiceProvider calss below which does the binding
<?php
use Illuminate\Support\ServiceProvider;
class MessagingServiceProvider extends ServiceProvider {
/**
* Register the service provider.
*
* #return void
*/
public function register() {
App::bind('messaging', function()
{
return new \Messaging\Messaging;
}
);
}
}
Below is my facade class that I created for me to use it in the way I wanted to
<?php
use Illuminate\Support\Facades\Facade;
class Messaging extends Facade
{
/**
* Get the registered name of the component.
*
* #return string
*/
protected static function getFacadeAccessor() { return 'messaging'; }
}
I have placed my MessagingServiceProvider.php inside a folder called serviceproviders inside app folder, and placed the messaging.php(the file containing the facade class) inside a folder called facade in the app folder and added them to auto load.
Below is the model class for the facade
<?php
namespace Messaging;
use Eloquent; // if you're extending Eloquent
class Messaging extends Eloquent {
...
}
After doing all this still I am getting an error "Non-static method Messaging\Messaging::getConversationMessages() should not be called statically, assuming $this from incompatible context"
You are not using your Facade. Try to namespace it and use a different name:
<?php namespace Messaging;
use Illuminate\Support\Facades\Facade;
class MessagingFacade extends Facade
{
...
}
Then you
composer dumpautoload
And try to use it this way:
Messaging\MessagingFacade::getConversationMessages()
If it works for you, you create an alias for it in app/config/app.php.
'Messaging' => 'Messaging\MessagingFacade',
And you should be able to use it as:
Messaging::getConversationMessages()
About namespaced classes, every time you need to a class from another namespace, you need to go root:
\DB::whatever();
Related
I am trying to make my own custom Facade and register is with a custom service container and finally creating a custom alias for this facade.
I am not sure what part is not working, maybe there is a problem with the service container registering or maybe with the alias?
Let's start with my facade:
/**
*
* #see \App\Library\Facades\ViewWrapper\CustomView
*/
class CustomViewFacade extends Facade
{
protected static function getFacadeAccessor()
{
return 'customview';
}
}
My CustomView class with the logic and the show function
namespace App\Library\Facades\ViewWrapper;
...
class CustomView
{
public function show(...) { ... }
...
}
My CustomViewServiceProvider
namespace App\Providers;
...
class CustomViewServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->singleton(CustomViewFacade::class);
$this->app->alias(CustomViewFacade::class, 'customview');
}
}
How I register the provider in the config\app.php
App\Providers\CustomViewServiceProvider::class,
How I create the alias in the config\app.php
'CustomView' => App\Library\Facades\ViewWrapper\CustomViewFacade::class
In my controller I use the facade like this:
use CustomView;
...
public function show(ImageRequest $imagerequest)
{
return CustomView::show(...);
}
I get the following error in the controller:
Class 'CustomView' not found
What am I doing wrong here?
EDIT
After clearing config and composer autoload dump I get the following error:
Call to undefined method App\Library\Facades\ViewWrapper\CustomViewFacade::show()
I think you haven't quite clearly understood how Facades work. They are just an easy way to access your services without having to deal with dependency injection. I'm not a fan of this methodology, but here's how you do it properly.
You need to bind your actual service to the container, not the facade. The facade is almost just a symbolic link to your service within the container.
You need to import the actual service, not the facade. Laravel will automatically bind your dependency in the type-hinted variable, thanks to its behind the scenes magic.
Use:
use App\Library\Facades\ViewWrapper\CustomView;
(small note: your namespace here should be your service's namespace, be aware to not mix up the semantic between facade and service. The service contains the logic, the facade is just an accessor to a service that is already injected. This is important!!)
Instead of:
use CustomView;
It should solve the issue.
Also, I'd suggest you do define how the class should be constructed and injected in the Service Container by using a Closure in the bootstrap function.
class CustomViewServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->singleton(CustomView::class, function () {
return new CustomView(...);
);
}
}
Also, the alias function is not necessary in your case. It'd simply allow you to access the service by using the customview key in the Service Container.
Just define the Facade in your config/app.php file.
Another small suggestion: use PHP 7 class selectors instead of strings in your facade accessor definition. For example: CustomView::class intead of customview. It makes your code neater and easier to read.
Please run below command and check:
php artisan config:cache
php artisan cache:clear
I want to create aliases in laravel like Auth so that i can use it in view just like
Auth::user().
For example, i want to return data from my setting table and want to use it like
Setting::method()->value. in view and use Setting in controllers.
What should i create for this Facades Or Service Providers? Provide me some procedures.
I tried using Service Providers but i am confused how to call database there.
This will be a long answer, using Laravel 5.4.
You need a service class (in this case, it's a concrete class behind the facade). I made it inside app/Services folder:
namespace App\Services;
use Illuminate\Database\DatabaseManager;
class Setting
{
protected $db;
public function __construct(DatabaseManager $db)
{
$this->db = $db;
}
public function method()
{
return;
}
}
As you see, I inject the database inside that concrete class. This is the magic of Laravel IoC. It will automatically resolve any dependency into your concrete class.
Next, create a facade. I made it inside app/Facades folder:
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class Setting extends Facade
{
/**
* Get the registered name of the component.
*
* #return string
*/
protected static function getFacadeAccessor()
{
return 'setting';
}
}
Notice the setting string returned from getFacadeAccessor. You need to register this service name later to the Container (IoC). The magic behind this facade is, it's automatically call (proxy) any static method to the instance method of concrete class, in this case you can call:
Service::method()
Register the service to the container. Inside your AppServiceProvider
namespace App\Providers;
use App\Services\Setting;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
// ...
/**
* Register any application services.
*
* #return void
*/
public function register()
{
// ...
$this->app->singleton(Setting::class);
$this->app->alias(Setting::class, 'setting');
}
}
In this Service Provider, I declare that Setting service is a singleton service. Which means, you can use Setting service in another place without re-initialize class, in another words you are using the same instance across file. Last, I tell the container that Setting service has another alias, name setting, so Container can figure out which Concrete Class behind App/Facade/Setting.
For aliasing, as mentioned by apokryfos. Register your facade alias inside config/app.php, find the section aliases and add this line:
'aliases' => [
// ...
'Setting' => App\Facades\Setting::class,
],
After this you can call your facade like this:
use Setting;
Setting::method();
Hope this helps.
I am trying to inject a Manager class into toe Service Container of Lumen. My goal is to have a single instance of LogManager which is available in the whole application via app(LogManager::class).
Everytime i try to access this shortcut i get the following exeption:
[2017-03-23 16:42:51] lumen.ERROR: ReflectionException: Class LogManager does not
exist in /vendor/illuminate/container/Container.php:681
LogManager.php (i placed that class in the same location where my models are (app/LogManager.php))
<?php
namespace App;
use App\LogEntry;
class LogManager
{
...
}
AppServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\LogManager;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->singleton(LogManager::class, function ($app) {
return new LogManager();
});
}
}
I uncommented the line $app->register(App\Providers\AppServiceProvider::class); in bootstrap/app.php
I think that i missed something with the correct namespacing or placement of the classes espaccially LogManager. Maybe some one is willing to give me a hint?
If you need some more informations just give me a hint!
Your class and your service provider look fine. However, wherever you're calling app(LogManager::class) also needs to know the fully qualified name of the class.
Either make sure you have use App\LogManager at the top of the file, or change your call to app(\App\LogManager::class).
Without knowing how Laravel facades work, based on my PHP knowledge, I tried to extend Storage facade to add some new functionalities.
I have this code:
class MyStorageFacade extends Facade {
/**
* Get the binding in the IoC container
*
* #return string
*/
protected static function getFacadeAccessor()
{
return 'MyStorage'; // the IoC binding.
}
}
While booting service provider:
$this->app->bind('MyStorage',function($app){
return new MyStorage($app);
});
And facade is:
class MyStorage extends \Illuminate\Support\Facades\Storage{
}
When using it:
use Namespace\MyStorage\MyStorageFacade as MyStorage;
MyStorage::disk('local');
I get this error:
FatalThrowableError in Facade.php line 237: Call to undefined method Namespace\MyStorage\MyStorage::disk()
Also tried to extend MyStorage form Illuminate\Filesystem\Filesystem and got the same error in other way:
BadMethodCallException in Macroable.php line 74: Method disk does not exist.
Your MyStorage class needs to extend FilesystemManager not the Storage facade class.
class MyStorage extends \Illuminate\Filesystem\FilesystemManager {
....
}
A facade is just a convenience class that will convert a static call Facade::method to resolove("binding")->method (more or less). You need to extend from Filesystem, register that in IoC, keep your facade as it is, and use the Facade as a static.
The facade:
class MyStorageFacade extends Facade {
protected static function getFacadeAccessor()
{
return 'MyStorage'; // This one is fine
}
}
Your custom storage class:
class MyStorage extends Illuminate\Filesystem\FilesystemManager {
}
In any service provider (e.g. AppServiceProvider)
$this->app->bind('MyStorage',function($app){
return new MyStorage($app);
});
Then when you need to use it use it as:
MyStorageFacade::disk(); //Should work.
I am attempting to create a facade within laravel 4.1. I have created the facade, service provider and the class, to no avail. I followed numerous "how to's" including the advanced video for custom facades on Laracasts. No matter how many times I try, I end up with the exception of Non-static method Custom\Helpers\Helper::doSomething() should not be called statically
Here is my code...
HelpersServiceProvider.php
<?php namespace Custom\Helpers;
use Illuminate\Support\ServiceProvider;
class HelpersServiceProvider extends ServiceProvider {
public function register()
{
$this->app->bind('trial','Custom\Helpers\Helper');
}
}
HelpersFacade.php
<?php namespace Custom\Facades;
use Illuminate\Support\Facades\Facade;
class Helper extends Facade {
protected static function getFacadeAccessor()
{
return 'trial';
}
}
Helpers.php
<?php namespace Custom\Helpers;
class Helper {
public function doSomething()
{
return 'Hello';
}
}
I add the service provider to my app.php file and register the facade alias
'Custom\Helpers\HelpersServiceProvider',
'Helper' => 'Custom\Facades\Helper',
Then when I try to access it via a Static call (yes, I know it's not really static) or via the service provider directly I get the exception error.
Scratching my head on this one...
It looks like you have an incorrectly named class (or file):
HelpersFacade.php
class Helper extends Facade {
Additionally, your Helper class is in Helpers.php. Those need to match, also.