Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

crushedcoder's avatar

Applying Design patterns in Laravel

I want to know how design patterns will helpful be in laravel with real example and frequently use design pattern for app?

0 likes
8 replies
papa's avatar

First think about using Service Layer Design Pattern and Repository Design Pattern with Constructor Dependency Injection.

papa's avatar

Imagine you have a Controller

class MyController extends Controller
{
    protected $userService;

    public function __construct(
        UserServiceInterface $userService
    )
    {
        $this->userService = $userService;
    }
    public function index()
    {
        return view('test')->with(
            'user' => $this->userService->getUser()
        )
    }
}

interface userServiceInterface
{
    public function getUser();
}
class userService implement userServiceInterface
{
    public function getUser()
    {
        return Auth::user();
    }
}

class UserServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->bind(UserServiceInterface::class, UserService::class);
    }
}


The same classes for Repository: 
    UserService => UserRepository
    UserServiceInterface => UserRepositoryInterface

Then the controllers call  services which call repositories to get data
1 like
shez1983's avatar

i am not sure about @papa example - you dont want to create wrapper classes which make no sense but bloat your code.

try to apply SOLID Principles to your classes (do some research on what this is, laracasts have videos but you can get free vidoes on Youtube/google)

try to create wrapper func to create complicated classes for example: if when u create a product, u need to create variants, prices, images etc.. then wrap it up into one service class (Product) with method called create ().. (this is factory pattern).

try to use interfaces/and polymorphism instead of doing something like:

if type == 'this'
     do this
else if .. 
     do that.
...

do this:

$class = getType($type);
$class->doStuff

Again google it - one result thatcame up is: https://refactoring.guru/replace-conditional-with-polymorphism


Finally if your project/codebase is small.. then try not to go down into these patterns just for the sakes of it unless you want to learn in which case small code base is perfect.
patoui's avatar

TLDR; follow official docs, apply design pattern when project size becomes too large to reason through easily

I'd like to offer some advice, and I reserve the right to change my opinion :D

I've been working on some non-trivial sized repositories (largest being just shy of 100 000 lines of code, php files only, not including vendor directory). At the beginning we thought it would be useful to follow a design pattern, we decided to follow the repository pattern before even writing any substantial code. Not a bad choice, but VERY premature.

I want to make this very clear, a design pattern CAN and IS useful when the code base starts to become difficult to read through and/or work with.

That being said before you get to that size of a project... Follow the way it's done in the official documentation.

I want to break it down as to why you would do this:

  1. Consistency

If everyone contributing to the code base is following the documentation it makes it easier for follow contributors to read through code.

  1. Onboarding

When a new contributor needs to get up and running it's a breeze. Questions like "how to do X task within the organizations framework/design pattern" is simply a matter of pointing them to the official documentation.

  1. Efficiency

There's something to be said about "not fighting the framework" and just using the tools provided to you (until you need to reach for something more complex). By accepting some of the assumptions/decisions the framework has made for you and now having consistent code across the board, it becomes easy to implement simple to complex features and even easier for fellow contributors to make changes to those features. Having a design pattern can impede this process, especially for those unfamiliar with the specific design pattern as it requires them to research it

In closing, I'd like to reiterate that I am not against design patterns, I just think people implement them prematurely.

At the end of the day, it's a personal choice, pick what works best for you, your company, and your fellow contributors.

2 likes
lostdreamer_nl's avatar

See the video for Code Katas "The Gilded Rose" for a great example of how code is written, and how is could be written if you understand the problem being solved (and thus, know which design pattern fits the need)

https://laracasts.com/series/code-katas-in-php/episodes/7

It's basically a lesson about how to restructure a bunch of if else statements into a pattern that is more easily understood.

1 like
papa's avatar

Think about Strategy and Factory Patterns

class PaymentFactory
{
    private $payments = [
        'paypal' => PayByPaypal::class
    ];

    public function createPaymentObject(string $payment)
    {
        $paymentClass = $this->payments[$payment];

        if (class_exists($paymentClass)) {
            return new $paymentClass;
        }

    // exception
    }
}

trait PaymentTrait
{
    protected $paymentsTypes = [
        'paypal' => 'Paypal'
    ];

    public function getPaymentTypes(): array
    {
        return $this->paymentsTypes;
    }
}

interface PaymentStrategy
{
    public function pay($config);   
}

abstract class PaymentBase implements PaymentStrategy
{
    public function pay($config)
    {
        return $this->doPay($config);
    }
    
}

class PayByPayPal extends PaymentBase
{
    public function doPay($config)
    {
        // here you will implement the PayPal API
    }
}

class PaymentController extends Controller
{
    public function pay(Request $request)
    {
    $config = Config::get('payments.paypal');
        Session::put('payment', $request->input('payment'));

        return ((new PaymentFactory())->createPaymentObject($request->input('payment')))->pay($config);
    }
}

You can use the Trait to get the payments in the front end

Please or to participate in this conversation.