Skip to content

Artisan command ​

Run the command with no arguments for a step-by-step form:

bash
php artisan make:custom-field

The command asks for each part of the field in order. It checks every answer as soon as you give it:

StepChecked right awayCan skip
Where to create it (migration or database)defaults to migration
Modelthe class exists
Scope (database mode only)the record existsyes, for a global field
Keyformat, existing fields, a migration that hasn't run yet, the model's columns and methods
Labellengthdefaults to the key as a headline
Typeregistereddefaults to text
Options (select types)at least one, no duplicatesan empty value ends the list
Requireddefaults to no
Descriptionyes
Extra validation rulesevery rule existsyes

Then the command shows a summary and asks before it creates anything.

Options ​

Each option skips its question. With --no-interaction, the key, --model and --type are required:

bash
php artisan make:custom-field tax_bracket \
    --model=User --type=select --options="a:Bracket A,b:Bracket B" \
    --required --rules="string" --description="Used for invoices" --no-interaction
OptionMeaning
key (argument)The field key
--modelA model class, a short name such as User (found in App\Models), or a morph alias
--typeA registered field type
--labelDefaults to the key as a headline
--optionsChoices for select types: value:Label,value:Label. A value without a label uses itself as the label.
--rulesExtra Laravel rules, separated by |
--descriptionHelp text
--requiredMake the field required
--modemigration (default) or db
--scopeModel:id, for example Property:5. Database mode only.
--pathWhere to write the migration, relative to the base path
--forceSkip the production confirmation in database mode

A rule that contains |, such as some regexes, can't go in --rules. Add it to the generated migration by hand.

Migration mode (default) ​

The command writes database/migrations/{timestamp}_add_tax_bracket_custom_field_to_users.php:

php
public function up(): void
{
    CustomFields::global()->create([
        'model' => \App\Models\User::class,
        'key' => 'tax_bracket',
        'label' => 'Tax Bracket',
        'type' => 'select',
        'settings' => [
            'options' => [
                'a' => 'Bracket A',
                'b' => 'Bracket B',
            ],
        ],
        'is_required' => true,
    ]);
}

public function down(): void
{
    CustomFields::global()->dropIfExists(\App\Models\User::class, 'tax_bracket');
}

Use migration mode for fields that your code depends on:

  • php artisan migrate creates the field in every environment.
  • The command doesn't touch the database, so it never asks for confirmation.
  • Migration mode doesn't allow a scope, because record ids differ between environments.

WARNING

Rolling back the migration deletes the field with all its values.

Database mode ​

--mode=db creates the field on the current database right away and prints its id. Use it for one-off fields on a live system, or for scoped fields:

bash
php artisan make:custom-field vip_reference --mode=db --scope=Property:5

In production the command asks for confirmation first, like php artisan migrate. --force skips the question.

Released under the MIT License.