Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

octal's avatar
Level 1

Best way to let user add fields to model

Hi, I'm writing a Laravel app and I need the ability to let user add custom fields to existing model. I mean user will add aditional attributes to items in a table (color, date, size, ...). What's the best way to handle that in Laravel? Should I create dynamically a migration, and execute it in order to let Eloquent handle automatically newly added fields? (on the view side I already have dynamic loading and visualisation of my fields working).

Regards

0 likes
5 replies
kokoshneta's avatar

Definitely not, no. Don’t store custom attributes as columns in your (product? user? something else?) table. You’d only end up with a table containing thousands of columns, which severely impacts your database performance and is completely impossible to manage.

Instead, I would have a separate table to store such attributes. Let’s say your main model is Product and the table is products. I would then make a ProductAttribute model and a corresponding product_attributes table that has the columns id, product_id, name, and value (plus timestamps if you need them). Make a unique index from product_id + name if you only want users to be able to add one instance of each custom field to each product.

Any custom fields your users add will then simply be a row in this table; e.g.,

// products

| id |  name   |
|----|---------|
|  1 | Shirt   |
|  2 | T-shirt |
|  3 | Jeans   |

// product_attributes

| id | product_id | name  | value |
|----|------------|-------|-------|
|  1 |          1 | color | Blue  |
|  2 |          1 | size  | M     |
|  3 |          2 | color | Green |
|  4 |          2 | size  | L     |

In your Product model, you then have a simple relationship to load all custom attributes, which you can eager-load to get everything at once:

// Product model
public function custom_attributes() {
	return $this->hasMany(ProductAttributes::class);
}

// Controller
$products = Product::with('custom_attributes')->where(...)->get();
1 like
octal's avatar
Level 1

@ismaile The problem with JSON is that I would not be able to do any SQL request on it, and I can't use Eloquent methods to find and update the model.

AddWebContribution's avatar

You can use Laravel's built-in migrations to handle adding custom fields to an existing model. However, it's not recommended to create a new migration dynamically every time the user adds a new custom field.

A better approach is to have a separate table to store the custom fields, where each row represents a single custom field for an item. Here's an example of how you can implement this in Laravel:

  1. Create a new table to store the custom fields:
    				php artisan make:migration create_custom_fields_table
    
  2. In the up method of the newly created migration, define the table structure:
      public function up()
    			{
    				Schema::create('custom_fields', function (Blueprint $table) {
        				$table->id();
        				$table->unsignedBigInteger('item_id');
        				$table->string('field_name');
        				$table->text('field_value');
        				$table->timestamps();
    
        				$table->foreign('item_id')->references('id')->on('items')->onDelete('cascade');
    				});
    			}
    
  3. Run the migration to create the custom_fields table:
    php artisan migrate
    
  4. Create a new Eloquent model CustomField to represent the custom fields:
    php artisan make:model CustomField
    
  5. In the CustomField model, define the relationship between the custom fields and the items:
    		class CustomField extends Model
    				{
    					public function item()
    					{
        					return $this->belongsTo(Item::class);
    						}
    				}
    
  6. In the Item model, define the relationship between the items and the custom fields:
    class Item extends Model
    				{
    					 public function customFields()
    					{
        					return $this->hasMany(CustomField::class);
    					}
    				}
    
  7. In your controller or other logic, you can add new custom fields for an item like this:
    						$item = Item::find($itemId);
    						$customField = new CustomField;
    						$customField->field_name = $fieldName;
    						$customField->field_value = $fieldValue;
    						$item->customFields()->save($customField);
    

This way, you can dynamically add custom fields for each item, and Eloquent will handle the database operations automatically. The custom fields will be stored in the separate custom_fields table, and you can retrieve and display them along with the other item data.

octal's avatar
Level 1

@saurabhd But that means the name of the field will be duplicated with each value entered for any product.

Maybe I can reuse your solution but encode the custom fields with custom_field_id and ad an additional table that would contain the name of the field. This will avoid storing the name each time and will store a numeric key instead. But I don't know how will the affect the needed joins to retrieve the whole info for a model.

Please or to participate in this conversation.