So I've implemented a service structure that a stackoverflow user suggested to me in this post. I've got it mostly working but I'm running into the error:
Class 'App\Services\Mailer\Facades\Mailer' not found
My service folder structure looks like this:
app
| App
| | Services
| | | Mailer
| | | | Mailer.php
| | | | MailerFacade.php
| | | | MailerServiceProvider.php
Each of the files in the Mailer directory are namespaced as:
<?php namespace App\Services\Mailer;
Except for the Facade which is namespaced as the following per the example in this blog:
<?php namespace App\Services\Mailer\Facades;
I put a test method in my Mailer.php
file's Mailer
class:
<?php namespace App\Services\Mailer;
//base service class
class Mailer {
public function sayHi(){
return "hello!";
}
}
I then created the facade:
<?php namespace App\Services\Mailer\Facades;
// Facade for Mailer
use Illuminate\Support\Facades\Facade;
class Mailer extends Facade {
protected static function getFacadeAccessor(){ return 'mailer'; }
}
Then I created the Service Provider to hook them all together:
<?php namespace App\Services\Mailer;
// Mailer's service provider
use Illuminate\Support\ServiceProvider;
class MailerServiceProvider extends ServiceProvider {
public function register(){
$this->app['mailer'] = $this->app->share( function ($app){
return new App\Services\Mailer\Mailer;
});
$this->app->booting( function (){
$loader = \Illuminate\Foundation\AliasLoader::getInstance();
$loader->alias('Mailer', 'App\Services\Mailer\Facades\Mailer');
});
}
}
THe loader for the facade is pointing to the correct namespace, 'App\Services\Mailer\Facades\Mailer'
, but when I try calling the method in one of my controllers like so:
public function showMe(){
return Mailer::sayHi();
}
I get the message I noted at the top.
I tried putting the facade into a subfolder of the Mailer
directory called Facade
so that the namespace and folder structure matched exactly, but I got the same error.
I read and re-read the example, the original stackoverflow post, the composer documentation on psr-4
to make sure I wasn't referencing anything incorrectly, and I can't seem to figure it out.
Can anyone point me in the right direction?
EDIT:
So I took a step back and created a vanilla laravel project and tried to add in a service the same way I'm trying in my main project. It's running into a similar error.
Here's a screen shot of every file involved:
Process:
App/Services/Greetings
directory structurecomposer.json
fileGreetings
GreetingsFacade
class that returns the string 'greetings' for the `getFacadeAccessor methodGreetingsServiceProvider
and added the register method with it's commandsGreetings
servicecomposer dump-autoload
and loaded my routeWhen I load my page I get the error "Class 'App\Services\Greetings\App\Services\Greetings\Greetings' not found" :(
According to your directory structure:
app
| App
| | Services
| | | Mailer
| | | | Mailer.php
| | | | MailerFacade.php
| | | | MailerServiceProvider.php
Your classes namespaces must be:
Service
<?php namespace App\Services\Mailer;
class Mailer {}
Service Provider
<?php namespace App\Services\Mailer;
class MailerServiceProvider {}
Facade
<?php namespace App\Services\Mailer;
class MailerFacade {}
And you autoloader:
"autoload": {
"psr-4": {
"App\\": "app/App"
},
},
For it to work the way you are trying to do, your directory structure would have to be
app
| App
| | Services
| | | Mailer
| | | ├── Facades
| | | | └── Facade.php
| | | | Mailer.php
| | | | MailerServiceProvider.php
EDIT:
In your Greetings namespace, change from:
return new App\Services\Greetings\Greetings;
to
return new Greetings;
And it should work because they are in the same namespace. For an easy reading of the code, add
use App\Services\Greetings\Greetings;
In the top of your .php file.
psr-4 expects your directory structure to reflect the namespace structure.
In order to autoload a class App\Services\Mailer\Facades\Mailer
, it will look for the file App/Services/Mailer/Facades/Mailer.php
.
Additionally, the facade accessor mailer
(thus also the IoC-Container slug mailer
) is already used by Illuminate\Support\Facades\Mail
.
Try something different like my_mailer
:
<?php namespace App\Services\Mailer\Facades;
// Facade for Mailer
use Illuminate\Support\Facades\Facade;
class Mailer extends Facade {
protected static function getFacadeAccessor(){ return 'my_mailer'; }
}
and
<?php namespace App\Services\Mailer;
// Mailer's service provider
use Illuminate\Support\ServiceProvider;
class MailerServiceProvider extends ServiceProvider {
public function register(){
$this->app['my_mailer'] = $this->app->share( function ($app){
return new App\Services\Mailer\Mailer;
});
$this->app->booting( function (){
$loader = \Illuminate\Foundation\AliasLoader::getInstance();
$loader->alias('Mailer', 'App\Services\Mailer\Facades\Mailer');
});
}
}