Starting out Laravel I heard a lot of good advice, particularly on Laracast. But others are confusing, particularly on MVC. The common question is where do you put business logic. You’ll hear that you want to keep your controllers skinny and models thin. What the hell?
Using a service layer is the answer if you dig deeper. But service layers are not exactly covered in the Laravel documentation nor part of any guides and learning modules. But here’s what I understand so far.
Put your extra business logic in a Service class and import it into your controller.
Here’s a good excerpt from Travis Britz on SO.
Services, on the other hand, are an easy way to encapsulate the logic around a component, and they may do more than one thing… Consider if you didn’t store books by inserting them into your database, but instead by posting to an external API. All of these requests share logic for authenticating to the external web service (like adding headers to requests), and your BookRepository class can encapsulate that re-usable logic. You can use this service class inside of scheduled artisan commands, web controllers, api controllers, jobs, middleware, etc. — without repeating code.
P. Ellul shows what this might look like.
What about creating a Services folder under app/, and use Controller dependency injection.
MyService.php
namespace App\Services;
use App\Models\Bar;
class MyService
{
public function foo(Bar $bar)
{
// do things
}
}
MyController.php
namespace App\Http\Controllers;
use App\Services\MyService;
use App\Models\Bar;
class MyController extends Controller
{
protected $myService;
public function __construct(MyService $myService)
{
$this->myService = $myService;
}
public function handleRequest(Bar $bar)
{
$this->myService->foo($bar);
}
}
As you can see, it’s a simple class abstraction and instantiating the class in the controller construct. If it’s not a third-party service you could bypass the construct and call a new() class. And it’s not a problem to create your own Services folder and store it there.
Thanks for this. It is a simple concept (and simple implementation), but I am having to learn Laravel after working in ASP.net MVC for years, so it helps to just have someone point out the obvious.
Yeah, I think I didn’t understand it the first time around because it was too obvious.
Seems like a good way. Much better than the stupid and completely unnecessary Repository Pattern.
I thought I am the only one not in love with this pattern
Agree with you
it seems a bit messy to me as you end up with code like this:
$this->barService->foo($bar);
Coming from a project using the Yii framework where we used a “thin” base model and then a “Service” model which inherits the base model. so this would end up with
app > Models
Bar.php – service class which inherits Bar model
app > Models > Base
BarBase.php – “thin” model
I can see that this might be confusing so you could reverse it:
app > Models
Bar.php – “thin” model
app > Services
BarService.php – service class which inherits Bar model
namespace App\Services;
use App\Models\Bar;
class BarService extends Bar
{
public function foo()
{
// do things
}
}
then your controller could instantiate the service class instead:
public function handleRequest(BarService $bar)
{
$bar->foo();
}
Would that be an OK design pattern?
I’ve seen this pattern too. I don’t see why not.