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

thesimons's avatar

Redirect()->route('xxx') into functions

Hello,

I have a create a function named cancelSubscription that cancel a subscription. Easy. The challenging part is that this function can be used both in the admin both in the frontend: admins and users can cancel subscriptions (in case of users their own subscriptions).

As you may understand, the return that I commented, would change based on being in the admin or frontend.

What's the most elegant and effective way to change the route based on where the function is called from?

public function cancelSubscription(Request $request, $id)
    {
        $subscription = Subscription::findOrFail($id);
        $subscription->status = 'cancelled';
        $subscription->save();

        # return redirect()->route('admin.customers.subscriptions')->with('success', 'Subscription cancelled successfully.');
    }

Thanks, Simon

0 likes
8 replies
Glukinho's avatar

You should separate routes/controllers (application logic) and cancelling subscription (business login).

Specifically, create new class App\Actions\CancelSubscriptionAction with one method:

public function execute (Subscription $subscription)
{
    $subscription->status = 'cancelled';
    $subscription->save
}

Then, in routes/web.php you should have something like:

Route::post('/subscription/{subscription}/cancel', [ SubscriptionController::class, 'cancel' ]);
Route::post('/admin/subscription/{subscription}/cancel', [ AdminSubscriptionController::class, 'cancel' ]);

And separate controllers for users and admins which are responsible for calling your action and returning result to user the way you need (note they return different routes, but call the same action):

class SubscriptionController extends Controller
{
	public function cancel(Subscription $subscription)
	{
		(new CancelSubscriptionAction($subscription))->execute();

		return redirect()->route('users.customers.subscriptions')->with('success', 'Subscription cancelled successfully.');
	}
}


class AdminSubscriptionController extends Controller
{
	public function cancel(Subscription $subscription)
	{
		(new CancelSubscriptionAction($subscription))->execute();

		return redirect()->route('admin.customers.subscriptions')->with('success', 'Subscription cancelled successfully.');
	}
}

Note that integer subscription id is not used anywhere, only typed class Subscription! Laravel handles it itself in very convenient way.

Snapey's avatar

if this is a post request, then return back() ?

Snapey's avatar

But tell me, how do you prevent a user cancelling someone else's subscription?

thesimons's avatar

@ghabe and @snapey

Good point, that was the "base" code just to show the logic. In the real implementation the customer reaches the cancel page with a token generated just for him expiring in 60 minutes, so token + subscription id belonging to the same member id "owner" of the token are required to cancel.

:)

Snapey's avatar

so token plus a different subscription id would be invalid? What you described does not seem to cover mischief

thesimons's avatar

@Snapey Thanks for your input I have improved the security. Here the logic:

  1. Customer enter an email into a form
  2. If the email exists in the members database, a new record is inserted in the customer_account_tokens table
  3. The record contains a token (32 chars unique) plus the member id of the member who requested access link
  4. A link is sent via email to the email on file
  5. By clicking on the link in the email, the system checks if tokens really exists and it's not expired
  6. All subscriptions for the member are listed
  7. In case the customer wants to cancel a subscription, he has a to click on a button that triggers a form using "code" and not anymore the "id" to set the subscription with status "cancelled"

The code of the subscription is a 10 chars unique code assigned at the time of the creation of the subscription.

Thanks, Simon

Snapey's avatar

or you could just check that the owner id of the subscription is the same as the current user.

Please or to participate in this conversation.