Override Name Collision in Laravel Cashier Models and Migration

Why you might need to do this

If your application already has a subscriptions, subscription_items, customers table, or models with the same name as Laravel Cashier, you will run into a naming collision where Laravel Cashier will try to use its own models and migrations, but your models might already have a relation called "subscriptions" or "subscription_items" which interferes with Laravel Cashier and breaks your billing functionality.

Solution: Override Laravel Cashier models and migrations

Publish the Cashier config and migrations:

php artisan vendor:publish --tag="cashier-config"
php artisan vendor:publish --tag="cashier-config"

Modify the cashier migrations, add a prefix (like stripe_ or cashier_) to the table names:

// File database/migrations/2019_05_03_000002_create_subscriptions_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('stripe_subscriptions', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id');
            $table->string('name');
            $table->string('stripe_id')->unique();
            $table->string('stripe_status');
            $table->string('stripe_price')->nullable();
            $table->integer('quantity')->nullable();
            $table->timestamp('trial_ends_at')->nullable();
            $table->timestamp('ends_at')->nullable();
            $table->timestamps();

            $table->index(['user_id', 'stripe_status']);
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('stripe_subscriptions');
    }
};

// File database/migrations/2019_05_03_000003_create_subscription_items_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('stripe_subscription_items', function (Blueprint $table) {
            $table->id();
            $table->foreignId('stripe_subscription_id');
            $table->string('stripe_id')->unique();
            $table->string('stripe_product');
            $table->string('stripe_price');
            $table->integer('quantity')->nullable();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('stripe_subscription_items');
    }
};

Then create new models that extend the Cashier models.

php artisan make:model StripeSubscription
php artisan make:model StripeSubscriptionItem

Extend the Cashier models, setting the $table property and using an alias for the class is optional, I just like to do it when I deal with third-party packages.

// File: app/Models/StripeSubscription.php
<?php

namespace App\Models;

use Laravel\Cashier\Subscription as CashierSubscription;

class StripeSubscription extends CashierSubscription
{
    protected $table = 'stripe_subscriptions';
}

// File: app/Models/StripeSubscriptionItem.php
<?php

namespace App\Models;

use Laravel\Cashier\SubscriptionItem as CashierSubscriptionItem;

class StripeSubscriptionItem extends CashierSubscriptionItem
{
    protected $table = 'stripe_subscription_items';
}

Finally, add this to your AppServiceProvider (or any other service provider that is loaded when your application starts):

// File: app/Providers/AppServiceProvider.php

use App\Models\StripeSubscription;
use App\Models\StripeSubscriptionItem;

class AppServiceProvider extends ServiceProvider
{
    public function register() { /* no changes in this method */ }
    public function boot()
    {
        Cashier::useSubscriptionModel(App\Models\StripeSubscription::class);
        Cashier::useSubscriptionItemModel(App\Models\StripeSubscriptionItem::class);
    }
}