lazerg's avatar
Level 5

Model add custom columns dynamically

I have a Laravel CRM and need to implement a function in the UI where the admin can navigate to the Order model, for example, and add static columns, such as a note column.

Additionally, all these model's extra (custom) columns should be displayed in the CRUD interface. Is there a Laravel package that meets this requirement?

P.S. Note is just an example, in real case it can be anything. For example If client want to add any static column to Order, it must be possible without developer interaction...

0 likes
3 replies
LaryAI's avatar
Level 58

To achieve the functionality of adding custom columns dynamically to your models in a Laravel application, you can use a combination of database migrations, Eloquent models, and a package like spatie/laravel-schemaless-attributes. This package allows you to store additional attributes in a JSON column, which can be very useful for dynamic fields.

Here’s a step-by-step solution:

  1. Install the Spatie Schemaless Attributes Package:

    First, you need to install the spatie/laravel-schemaless-attributes package. You can do this via Composer:

    composer require spatie/laravel-schemaless-attributes
    
  2. Add a JSON Column to Your Orders Table:

    Next, you need to add a JSON column to your orders table to store the custom attributes. You can do this by creating a new migration:

    php artisan make:migration add_custom_attributes_to_orders_table
    

    Then, update the migration file to add the JSON column:

    use Illuminate\Database\Migrations\Migration;
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Support\Facades\Schema;
    
    class AddCustomAttributesToOrdersTable extends Migration
    {
        public function up()
        {
            Schema::table('orders', function (Blueprint $table) {
                $table->json('custom_attributes')->nullable();
            });
        }
    
        public function down()
        {
            Schema::table('orders', function (Blueprint $table) {
                $table->dropColumn('custom_attributes');
            });
        }
    }
    

    Run the migration:

    php artisan migrate
    
  3. Update the Order Model:

    Now, update your Order model to use the HasSchemalessAttributes trait provided by the package:

    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Model;
    use Spatie\SchemalessAttributes\SchemalessAttributes;
    use Spatie\SchemalessAttributes\HasSchemalessAttributes;
    
    class Order extends Model
    {
        use HasSchemalessAttributes;
    
        protected $casts = [
            'custom_attributes' => 'array',
        ];
    
        public function getCustomAttributesAttribute(): SchemalessAttributes
        {
            return SchemalessAttributes::createForModel($this, 'custom_attributes');
        }
    }
    
  4. Add Custom Attributes via UI:

    In your controller, you can add logic to handle the addition of custom attributes. For example:

    namespace App\Http\Controllers;
    
    use App\Models\Order;
    use Illuminate\Http\Request;
    
    class OrderController extends Controller
    {
        public function addCustomAttribute(Request $request, Order $order)
        {
            $request->validate([
                'key' => 'required|string',
                'value' => 'required',
            ]);
    
            $order->custom_attributes->set($request->key, $request->value);
            $order->save();
    
            return redirect()->back()->with('success', 'Custom attribute added successfully.');
        }
    }
    
  5. Display Custom Attributes in CRUD Interface:

    Finally, in your views, you can display the custom attributes. For example, in your order details view:

    @foreach($order->custom_attributes as $key => $value)
        <p><strong>{{ $key }}:</strong> {{ $value }}</p>
    @endforeach
    

This solution allows you to dynamically add custom columns to your Order model and display them in your CRUD interface. The spatie/laravel-schemaless-attributes package makes it easy to handle schemaless attributes in a clean and efficient way.

1 like
lazerg's avatar
Level 5

@LaryAI But this applies for each model instance seperately. In my case, If I add note column, it must be added to all models and set null by default

Please or to participate in this conversation.