Too many fillable fields in model Laravel?

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company
# Too Many Fillable Fields in a Laravel Model: The Danger of Using `*` As developers working with large datasets, it's common to encounter scenarios where a database table has dozens or even hundreds of columns. When integrating this structure into an Eloquent model in Laravel, managing mass assignment becomes a critical security and architectural concern. The question arises when we consider using the shortcut `$fillable = ["*"];` to allow mass assignment for every field. Can we simply tell Laravel that all 200 fields are safe to be updated via input arrays? The short answer is: technically yes, but practically, **absolutely not**. This post will dive deep into why this approach is dangerous, explore the correct Laravel patterns for handling large models, and provide secure alternatives. --- ## Understanding Mass Assignment Protection In Laravel, Eloquent provides a crucial layer of security known as mass assignment protection. This mechanism prevents malicious users from updating columns in your database that you have not explicitly allowed them to modify through an incoming request (like a form submission). This protection is governed by two primary properties on your model: `$fillable` and `$guarded`. * **`$fillable`**: An array of attributes that are allowed to be mass-assigned. If an attribute is not listed here, Eloquent will block the update attempt. * **`$guarded`**: An array of attributes that are *not* allowed to be mass-assigned. By default, if `$fillable` is not defined, all attributes are guarded (i.e., `$guarded = ['*']`). When you use methods like `create()` or `$model->fill($data)`, Laravel checks these rules before writing data to the database. ## The Pitfall of Using `"*"` for Mass Assignment Your scenario involves a table with 200 fields, and you are considering setting: ```php protected $fillable = ["*"]; ``` While this technically allows mass assignment for all 200 fields, it completely disables the safety mechanism. In a production environment, this is considered a severe security vulnerability because it essentially grants any user who can submit data access to modify *any* field in that table, including sensitive columns like `is_admin`, `salary`, or internal audit flags, even if those fields were never intended for public input. This practice violates the principle of least privilege. Every piece of data should have explicit permission defined. If you are dealing with complex data structures, relying on a wildcard bypasses the necessary scrutiny that Laravel is designed to enforce. ## Best Practices for Handling Large Models Instead of using the dangerous `["*"]` approach, we must adopt more granular and secure strategies when managing large models, aligning with robust development practices advocated by teams working with frameworks like **Laravel Company**. ### 1. Explicitly Define Fillable Fields The primary solution is to explicitly list only those fields that are intended to be modifiable via mass assignment. If you have hundreds of fields, you should segment your model or use more sophisticated data handling methods. **Example of Secure Definition:** ```php class MyLargeModel extends Model { // Only allow mass assignment for the fields that users are permitted to change. protected $fillable = [ 'field_1', 'field_2', 'field_3', // ... list all necessary, non-sensitive fields explicitly 'field_200' ]; // If you need to guard everything else (e.g., internal timestamps or system flags), // ensure they are not in $fillable. } ``` ### 2. Use Form Requests for Input Validation For complex data insertion, especially with many fields, the best practice is to decouple data input from the model itself using **Form Requests**. Form Requests allow you to validate, authorize, and sanitize incoming data *before* it ever touches your Eloquent model. This is far more robust than relying solely on `$fillable`. ### 3. Handling Bulk Inserts (`Result::insert()`) When you use methods like `Result::insert($data)`, you are interacting directly with the Query Builder, which bypasses the full Eloquent model lifecycle (like casting and model events). While this is efficient for bulk operations, remember that if your data source ($data) is untrusted, validation must still occur upstream. Ensure that whatever array you pass to `insert` has already been rigorously validated against your security rules defined in `$fillable`. ## Conclusion In summary, while setting `$fillable = ["*"]` seems like a convenient shortcut for managing hundreds of fields, it sacrifices essential security and architectural integrity. As a senior developer, we must always prioritize explicit permissions. For large models in Laravel, the correct path involves explicitly defining `$fillable` based on business requirements and leveraging Laravel's built