Module Migrations

Concord CRM automatically registers all the migrations of a module that is generated with the module:make command. The module migration files are located in the modules/[ModuleName]/database/migrations directory.

You should use migrations in Concord CRM just as you would with the regular Laravel migration feature. This allows you to take advantage of Laravel's robust migration system while integrating seamlessly with the modular structure of Concord CRM.

Generating Migrations

To generate a module migration, you should use the module:make-migration command. Using this command will ensure the generation of a proper migration with accurate timestamps and will place the migration file in the correct location.

php artisan module:make-migration create_invoices_table Invoices

Each time a new migration exists, Concord CRM will prompt the user to perform the migration. For example, when updating your module, you don't need to write any additional checks to determine whether the user has run the migrations; this process is already managed by Concord CRM. The system automatically detects pending migrations and notifies the user, ensuring that all necessary database updates are applied without requiring extra code from the developer.

To test this functionality, after generating a migration, simply reload the page in Concord CRM. You will see a message prompting you to perform the migration, confirming that the system has recognized the new migration and is ready to apply it.

Handling Foreign Keys and Data Cleanup

When a module interacts with core tables or other modules table, it is crucial to maintain data integrity, especially when the module is deactivated or deleted. This section provides guidelines and best practices to manage foreign keys and related data effectively.

Foreign Key Constraints

If your module adds foreign key constraints to existing tables, use appropriate actions to maintain data integrity. For instance, using cascadeOnDelete or nullOnDelete can ensure related records are handled correctly.

$table->foreignId('user_id')
      ->constrained()
      ->nullOnDelete();

Handling Data on Module Deactivation:

Ensure that foreign keys and related data are managed appropriately when a module is deactivated. While deactivating, you should avoid deleting data to prevent loss when reactivating the module.

Data Cleanup on Module Deletion

Implement a cleanup process to handle any remaining data. When a module is deleted, manually check and clean up any orphaned foreign key references.

In the module bootstrap/module.php file you can register a handler to be executed when the module is being deleted.

use Modules\Core\Facades\Module;
use Illuminate\Contracts\Foundation\Application;

return Module::configure('invoices')
    ->deleting(function (Application $app) {
        // Perform clean up
    });

Resetting Migrations on Module Deletition

Depends on the module complexity, maybe the easiest way to remove all the data from the database is to reset the migrations of the module when the module is being deleted.

You can enable this feature in the module bootstrap/module.php file using the onDeleteResetMigrations method.

use Modules\Core\Facades\Module;
use Illuminate\Contracts\Foundation\Application;

return Module::configure('invoices')
    ->onDeleteResetMigrations()
    ...;

However, please note that you should drop any foreign keys in the down method of the migration before dropping columns with foreign keys.

public function down() : void
{
    Schema::table('invoices', function (Blueprint $table) {
        $table->dropForeign(['user_id']);
        $table->dropColumn('user_id');
    });
}