Field Types & Primary Keys
Fields are declared as name:type pairs, comma-separated:
php artisan make:fullapi Product --fields="name:string,price:decimal,stock:integer,meta:json"Supported types
| Type | Database column | PHP type | Validation rule |
|---|---|---|---|
string | VARCHAR(255) | string | string|max:255 |
text | TEXT | string | string |
integer / int | INTEGER | int | integer |
bigint | BIGINTEGER | int | integer |
boolean / bool | BOOLEAN | bool | boolean |
float / decimal | DECIMAL(8,2) | float | numeric |
json | JSON | array | array |
date | DATE | DateTimeInterface | date |
time | TIME | string | date_format:H:i,H:i:s |
datetime | DATETIME | DateTimeInterface | date |
timestamp | TIMESTAMP | DateTimeInterface | date |
uuid | UUID | string | uuid |
enum(a,b,...) | ENUM('a','b') | backed enum + cast | Rule::enum() |
Every type flows through the whole stack: migration column, validation rules, model cast, factory value, DTO property type and PHPDoc @property.
Native enum fields
php artisan make:fullapi Article --fields="title:string,status:enum(draft,published,archived)"One field definition produces the entire chain. Here is the code the command above writes, trimmed to the lines the enum touches:
namespace App\Enums;
enum ArticleStatus: string
{
case Draft = 'draft';
case Published = 'published';
case Archived = 'archived';
}/**
* @property int $id
* @property string $title
* @property ArticleStatus $status
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
*/
class Article extends Model
{
use HasFactory;
protected $fillable = ['title', 'status'];
protected function casts(): array
{
return [
'status' => ArticleStatus::class,
];
}
}public function rules(): array
{
return [
'title' => 'required|string|max:255',
'status' => ['required', Rule::enum(ArticleStatus::class)],
];
}public function definition(): array
{
return [
'title' => fake()->word(),
'status' => fake()->randomElement(ArticleStatus::cases()),
];
}Schema::create('articles', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->enum('status', ['draft', 'published', 'archived']);
$table->timestamps();
});The enum is named after the entity and the field, ArticleStatus here, so two entities can each have their own status.
In a schema file:
status: enum(draft,published) default=draftCustom primary keys
Append :primary (CLI) or the primary modifier (schema file) to make a field the primary key instead of the default auto-increment id:
php artisan make:fullapi Country --fields="code:string:primary,name:string"The whole stack follows automatically:
- Migration:
$table->string('code')->primary(), no$table->id() - Model:
$primaryKey,$incrementing = false,$keyTypedeclared - Incoming relations: the FK is named
country_code, typed like the key, with->references('code')in the migration andexists:countries,codein validation - Generated tests use
getKey()so they pass with either key style
Nullable, unique and defaults
The --fields string syntax keeps to name:type. For per-field constraints, use either the interactive wizard or a schema file, which accepts a shorthand or a mapping:
fields:
title: string
slug: string unique
content: text nullable
views: { type: integer, default: 0 }