muuucho's avatar
Level 11

How to keep “config” data the same over different environments.

Let's say that I have some tables that almost never change, but sometimes do a little. Some quick examples:

modules, like invoice, bookkeeping, employers…

id

name

permissions, like can_edit, can_view…

id

module_id

name

Chance is that a module or a permission is added over time. Should I keep them in tables and hardcode through phpMyAdmin or through some superAdmin crud?

Or should I keep them in arrays in a config file?

Pros and cons? Articles?

0 likes
3 replies
LaryAI's avatar
Level 58

When dealing with configuration data that is relatively static but may occasionally change, you have a few options. Each approach has its pros and cons, and the best choice depends on your specific use case and workflow. Here are some common strategies:

1. Database Tables

Pros:

  • Dynamic Updates: You can easily update the data without deploying code changes.
  • Centralized Management: If you have a superAdmin CRUD interface, it allows for centralized management of this data.
  • Relational Integrity: You can maintain relationships between different pieces of data (e.g., modules and permissions).

Cons:

  • Complexity: Requires database migrations and possibly more complex logic to handle changes.
  • Performance: Slightly slower than reading from a config file, though usually negligible.

Implementation: You can create tables for modules and permissions and manage them through a CRUD interface. This allows you to add, update, or delete entries as needed.

2. Config Files

Pros:

  • Simplicity: Easy to read and modify, especially for small datasets.
  • Performance: Faster read times since they are loaded into memory.

Cons:

  • Deployment Required: Any change requires a code deployment.
  • Limited Scalability: Not ideal for large datasets or complex relationships.

Implementation: You can store your configuration data in a PHP config file or a JSON/YAML file. For example:

// config/modules.php
return [
    'modules' => [
        ['id' => 1, 'name' => 'invoice'],
        ['id' => 2, 'name' => 'bookkeeping'],
        // Add more modules as needed
    ],
    'permissions' => [
        ['id' => 1, 'module_id' => 1, 'name' => 'can_edit'],
        ['id' => 2, 'module_id' => 1, 'name' => 'can_view'],
        // Add more permissions as needed
    ],
];

3. Hybrid Approach

You can combine both methods by storing the core configuration in files and allowing dynamic updates through the database. For example, you might load default values from a config file and allow overrides or additions via the database.

Pros:

  • Flexibility: You get the best of both worlds.
  • Fallback: If the database is unavailable, you can fall back to the config file.

Cons:

  • Complexity: More complex to implement and maintain.

Implementation: Load the initial configuration from a file and then merge it with any updates from the database.

// Load from config file
$config = include 'config/modules.php';

// Fetch updates from the database
$modulesFromDb = DB::table('modules')->get()->toArray();
$permissionsFromDb = DB::table('permissions')->get()->toArray();

// Merge or override as needed
$finalConfig = [
    'modules' => array_merge($config['modules'], $modulesFromDb),
    'permissions' => array_merge($config['permissions'], $permissionsFromDb),
];

Conclusion

Choose the approach that best fits your needs. If you expect frequent changes and need relational integrity, use the database. If changes are rare and simplicity is key, config files might be sufficient. For a balance, consider a hybrid approach.

martinbean's avatar
Level 80

@muuucho Unfortunately only you can answer this really. It depends on how granular your permissions are, and how frequently you’re going to be adding/updating/removing them.

I think personally, I’d go with a database, mainly because there are so many packages out there that will do this for you. Spatie famously has a package for everything… including roles and permissions (https://spatie.be/docs/laravel-permission).

You can also use migrations to insert any needed records, i.e. for new modules or permissions being introduced:

<?php // database/migrations/2024_11_29_124105_add_foo_module.php

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

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        DB::table('modules')->insert(['name' => 'foo']);
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        DB::table('modules')->where('name', '=', 'foo')->delete();
    }
};
1 like
muuucho's avatar
Level 11

@martinbean Thanks, great with your migration suggestion, I didn't think of that.

1 like

Please or to participate in this conversation.