'Laravel Spark - Defining a free plan

I am using Laravel Spark Next and I am trying to create a free plan. My application is charging users "Per seat" (# of projects)

My application, however, will always have one free project included. That means I need to offer two plans: one free and one paid

In my SparkServiceProvider, I have added this:

Spark::billable(User::class)->chargePerSeat('lejemål', function (User $billable) {
    $projects = return $billable->projects()->count();
    
    //The first project is always free.
    return match ($projects) {
        0, 1 => 0,
        default => $leases,
    };

});

As far as I understand, the "chargePerSeat" method simply calculate the price to charge the user. So in this case, if the user have 0 or 1 project and chooses to subscribe, the price to be paid is zero (as it should be).

However, I am trying to understand how a free plan should work. In the classic Spark, we could define a "free plan" in the configuration.

When users are creating projects, I have added the subscribed middleware as per the documentation:

Route::get('projects/create', CreateProject::class)
        ->name('projects.create')
        ->middleware('subscribed');

It seems like this middleware simply checks if there is an active subscription or not. If there is not, it redirects the user to the /billing page. However, if users simply just want to stay on the free plan, he/she should not need to create an active subscription.

How can I provide a "free plan" using Laravel Spark Next?



Solution 1:[1]

Although my solution is not using the “Per seat” pricing model, you can learn how to create a “Free” plan this way.

I originally wrote it on my blog, but I will write the important bits here.

You will need to create a “Free” plan in the config/spark.php file.


// ...

  'plans' => [
      [
          'name' => 'Free',
          'short_description' => 'This is the free plan',
          // Random _(not used by other plans)_ ID
          'monthly_id' => 1000,
          'features' => [
              '1 Project',
          ],
          'options' => [
              'projects' => 1,
          ],
          // IMPORTANT
          'archived' => true,
      ],

      // Other plans...
  ]

// ...

And then implement a method on your “User” model.

This method will get the current user's plan, or the “Free” plan if the user has no active plan.

Effectively falling back to the “Free” plan.


// ...

    public function getPlan()
    {
        $plan = $this->sparkPlan();

        if ($plan !== null) {
            return $plan;
        }

        // Fallback to "Free" plan
        $plan = Spark::plans('user')->firstWhere('name', '=', 'Free');

        return $plan;
    }

// ...

And then you can use it through your application.

$user = User::find(1);

$plan = $user->getPlan();

$plan->name; // "Free"

$plan->options['projects']; // 1

I recommend that you read my blog post, to understand a bit better how it works, but this is the gist.

I hope that this can help you, Oliver.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Alejandro Akbal