Reputation: 4180
I have an application where I have to deal with multiple vendors - each having their different implementation. For example, let's say Payment Systems, there are many vendors and banks.
There are a few things common, like implementation process. In each case, I have to give a callback URL to them to give me a response.
For now, I have two vendors - VendorPay and VendorA.
I will have two routes:
payment/callback/vendorpay
payment/callback/vendora
each of them call two methods in controller.
processVendorpay and processVendora
Now, if I want to add, lets say, 15 more vendors like this, will I have to create methods everytime I add new vendor? Is there any cleaner solution for this?
My controller right now looks like this:
class PaymentController extends BaseController
{
protected $vendorpay_validator, $vendora_validator, $transaction, $transaction_log, $vendor_product, $vendor_transaction;
public function __construct(VendorpayValidator $vendorpay_validator, VendorAValidator $vendora_validator, Transaction $transaction, TransactionLog $transaction_log, VendorProduct $vendor_product, VendorTransaction $vendor_transaction)
{
$this->vendorpay_validator = $vendorpay_validator;
$this->vendora_validator = $vendora_validator;
$this->transaction = $transaction;
$this->transaction_log = $transaction_log;
$this->vendor_product = $vendor_product;
$this->vendor_transaction = $vendor_transaction;
}
}
These four are the Model Repository Objects: $transaction, $transaction_log, $vendor_product, $vendor_transaction
If I have to add more venodrs, it keeps on adding validator object here. What would be a much cleaner way to do it?
One of the solutions that I thought was - for multiple routes, I just create one method. Now I'll check the route in this method and call the Factory Object basis on that.
Upvotes: 1
Views: 1843
Reputation: 33058
You should have just one route...
payment/callback/{vendor}
Then if you want to go the factory route (which I think would be a good idea in this case)...
class VendorValidatorFactory
{
private function __construct() {}
public static function getValidator($vendor)
{
switch ($vendor) {
case 'vendorpay':
return new VendorPayValidator;
case 'vendora':
return new VendarAValidator;
}
}
}
Remove the now unnecessary injections from your constructor and in the method which responds to your route, use the factory to grab the correct validator...
class SomeController extends Controller
{
public function __construct(Transaction $transaction, TransactionLog $transaction_log, VendorProduct $vendor_product, VendorTransaction $vendor_transaction)
{
$this->transaction = $transaction;
$this->transaction_log = $transaction_log;
$this->vendor_product = $vendor_product;
$this->vendor_transaction = $vendor_transaction;
}
public function processVendorResponse($vendor)
{
$validator = VendorValidatorFactory::getValidator($vendor);
}
}
And just a suggestion, every time you need to add a new method to your validator classes which your controller uses, add that to a ValidatorInterface
and make sure all your validators implement that ValidatorInterface
. This way when you need to add more, all you need to do is implement that interface and that should tell you exactly what functions you need to write. Then just update your factory method to include the new one and you are done. No more changing your controller, adding routes, or adding dependencies to your controller.
Upvotes: 1