Laravel新手求助:如何在SmartpaySController调用PaymentController方法
getPaymentFailed from SmartpaySController in Laravel Hey there! Since you're new to Laravel, let's walk through a couple of ways to call that method from your SmartpaySController—including a best practice that'll keep your code clean and maintainable in the long run.
Option 1: Directly Call the Controller Method (Quick, but Not Recommended)
You can instantiate the PaymentController and call the method directly, but you'll want to use Laravel's service container to handle any dependency injection (like your paymentRepo and quoteRepo):
use App\Http\Controllers\PaymentController; class SmartpaySController extends Controller { public function handlePaymentFailure($paymentId) { // Let Laravel's container resolve the controller with its dependencies $paymentController = app(PaymentController::class); return $paymentController->getPaymentFailed($paymentId); } }
Note:
This works for quick tests, but it's not ideal long-term. Controllers are meant to handle HTTP requests directly—calling their methods from other controllers creates tight coupling and makes your code harder to test and maintain.
Option 2: Extract Logic to a Service Class (Recommended Best Practice)
The better approach is to pull the business logic out of your controller into a reusable service class. This way, both PaymentController and SmartpaySController can use the same logic without duplicating code.
Step 1: Create a Payment Service
Make a new file app/Services/PaymentService.php:
namespace App\Services; use App\Repositories\PaymentRepository; use App\Repositories\QuoteRepository; use Illuminate\Http\Response; class PaymentService { protected $paymentRepo; protected $quoteRepo; // Inject your repositories via constructor public function __construct(PaymentRepository $paymentRepo, QuoteRepository $quoteRepo) { $this->paymentRepo = $paymentRepo; $this->quoteRepo = $quoteRepo; } // Extract the logic from getPaymentFailed here public function getPaymentFailedData($paymentId) { $transactionData = $this->paymentRepo->find($paymentId); if (!$transactionData) { // Handle missing transaction (e.g., return 404) abort(Response::HTTP_NOT_FOUND, 'Transaction not found'); } return [ 'quote' => $this->quoteRepo->getQuoteById($transactionData->quote_id), 'metaTitle' => 'Payment failed', 'returnMessage' => $transactionData->return_message ]; } }
Step 2: Update PaymentController to Use the Service
Modify your PaymentController to inject the service and use its method:
use App\Services\PaymentService; class PaymentController extends Controller { protected $paymentService; public function __construct(PaymentService $paymentService) { $this->paymentService = $paymentService; } public function getPaymentFailed($paymentId) { $data = $this->paymentService->getPaymentFailedData($paymentId); return view('payment::payment.quote_payment_failed', $data); } }
Step 3: Use the Service in SmartpaySController
Now you can easily reuse the same logic in SmartpaySController:
use App\Services\PaymentService; class SmartpaySController extends Controller { protected $paymentService; public function __construct(PaymentService $paymentService) { $this->paymentService = $paymentService; } public function processSmartpayFailure($paymentId) { // Get the payment failure data from the service $data = $this->paymentService->getPaymentFailedData($paymentId); // Either return the same view as PaymentController... return view('payment::payment.quote_payment_failed', $data); // ...or use the data to render a different view for Smartpay // return view('smartpay.payment_failed', $data); } }
Why This Is Better:
- Single Responsibility: Controllers handle HTTP requests, services handle business logic.
- Reusability: Any other controller or class can use this service later without duplicating code.
- Testability: Service classes are easier to unit test than controller methods tied to HTTP requests.
Option 3: Redirect to the PaymentController Route (If Applicable)
If you've already defined a route for getPaymentFailed, you can just redirect to that route instead of calling the method directly:
First, make sure your route exists in routes/web.php or routes/api.php:
Route::get('/payment/failed/{paymentId}', [PaymentController::class, 'getPaymentFailed'])->name('payment.failed');
Then in SmartpaySController:
public function redirectToFailurePage($paymentId) { return redirect()->route('payment.failed', ['paymentId' => $paymentId]); }
This is great if you just need to send the user to the existing payment failure page without modifying the logic.
内容的提问来源于stack exchange,提问作者Mayuri

