Obay Obay - 1 year ago 87
PHP Question

Is calling a Controller From Another Controller a good practice in Laravel?

I was able to implement a

, with a reusable
method, which accepts items and their prices, and creates a Paypal payment, and redirects to a Paypal payment page.

class PaypalController extends Controller {

private static $_api_context;

private static function initialize() {
//initialize api context

public static function postPayment($items, $currency, $description) {

//create item list, transaction, payment objects, etc

return redirect()->away($redirect_url); // redirect to paypal

is called statically by other controllers. For example, the
might call it to request payment from the user right after the user registers to my site:

class AuthController extends Controller {
public function postRegister(Request $request) {
return PaypalController::postPayment($items, 'JPY', 'description');

returns a
, which also returns it, to perform the redirect to the Paypal payment page.

I was wondering if this is a good design - a controller calling a different controller, is it?

If not, what would be a better way to do this? Maybe move my code from PaypalController into custom Service Provider, or custom Helper, or something else? I am very new to Laravel, and I would appreciate some guidance.

Answer Source

No it's not a good practice. You should abstract the business logic to a service/repository class. So for example:

Create an interface as Contract:

namespace App\Services\Paypal;

interface PaypalInterface {

     public function PostRegister(Array $array, /*More $params if necessary*/); 

Then implement the Contract:

namespace App\Services\Paypal;

class PaypalService implements PaypalInterface {

    // Must match the method signature declared in the interface
    public function PostRegister(Array $array, /*$More $params if necessary*/) {

        // Do the process here

Then use the contract/interface as dependency. So, in your PaypalController or in any other Controller you may (re)use it like:

namespace App\Http\Controllers;

use App\Http\Request;
use App\Services\Paypal\PaypalInterface;

class AuthController extends Controller {
    public function postPayment(Request $request, PaypalInterface $paypalService) {
        return $paypalService->postRegister($request->all());

In this case, register the binding (interface to implementation) in a service provider (Basically in AppServiceProvider). That's the basic workflow. Why an interface because, Controllers (Client/Consumer classes) should talk to Contract/Interface instead of a concrete implementation.

This article of mine may help you but remember this is not the 100% decoupled, it's still coupled with Laravel framework and you can even more decouple the Service.

Note: It's a best practice but don't blindly follow this approach for every projects/problems, just chose wisely when you should do it, it really depends on the context but don't just die for it. The current context is fine to follow this.