First think about using Service Layer Design Pattern and Repository Design Pattern with Constructor Dependency Injection.
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?
@PAPA - Could please elaborate with example to both ?
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
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.
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:
- Consistency
If everyone contributing to the code base is following the documentation it makes it easier for follow contributors to read through code.
- 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.
- 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.
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.
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
@PAPA - thanks to clear the concept
Please or to participate in this conversation.