Troubleshooting
Common Issues
"Model application instance has not been set"
Error: RuntimeException: Model application instance has not been set. Ensure ModelServiceProvider is registered.
Cause: You're using a model before the ModelServiceProvider has been registered and booted.
Fix: Register the provider in your plugin bootstrap:
use WPZylos\Framework\Model\ModelServiceProvider;
$app->register(new ModelServiceProvider());
Make sure this runs before any model operations.
Mass Assignment Not Working
Symptom: Attributes are not being set when using Model::create() or $model->fill().
Cause: The attribute is not listed in $fillable or is listed in $guarded.
Fix: Add the attribute to $fillable:
class User extends Model
{
protected array $fillable = ['name', 'email', 'role']; // Add missing attribute
}
Or use forceFill() to bypass protection:
$user->forceFill(['is_admin' => true]);
Attribute Casting Returns Wrong Type
Symptom: An attribute returns a string instead of the expected type.
Cause: The $casts array doesn't include the attribute.
Fix: Define the cast:
protected array $casts = [
'age' => 'integer',
'is_active' => 'bool',
'price' => 'float',
];
Null Casting
Symptom: A cast attribute returns null instead of the expected type.
Cause: Casting is intentionally skipped for null values. If the database column contains NULL, the model will return null regardless of the cast type.
Fix: Use a default value in your database schema, or handle null in your application logic:
$age = $user->age ?? 0;
Soft Deletes Not Filtering
Symptom: Soft-deleted records still appear in query results.
Cause: The SoftDeletes trait is not being used on the model.
Fix: Add the trait:
use WPZylos\Framework\Model\Concerns\SoftDeletes;
class Article extends Model
{
use SoftDeletes;
}
Events Not Firing
Symptom: Registered model events (creating, saving, etc.) are not executing.
Cause 1: Events are registered after the model has already been booted.
Fix: Register events in the static boot() method:
protected static function boot(): void
{
static::creating(function ($model) {
// This will fire
});
}
Cause 2: Event listeners from a previous test are still registered.
Fix: Flush listeners in test tearDown:
protected function tearDown(): void
{
MyModel::flushEventListeners();
}
Relationships Return null
Symptom: Accessing a relationship returns null.
Cause 1: The foreign key value is null on the model.
Fix: Ensure the foreign key is set:
$post = Post::find(1);
var_dump($post->getAttributes()); // Check that 'user_id' has a value
Cause 2: The relationship method doesn't match the property name.
Fix: The property name must match the method name exactly:
// Method name: posts()
public function posts()
{
return $this->hasMany(Post::class);
}
// Access via same name
$user->posts; // Good: Works
$user->post; // Bad: Will not work
Dirty Tracking Issues
Symptom: isDirty() returns unexpected results.
Cause: The original attributes were not synced after loading.
Info: isDirty() compares current attributes against the $original snapshot. The snapshot is set:
- When
fillFromRow()is called (loading from DB) - When
syncOriginal()is called manually - After a successful
save()orupdate()
"Call to undefined method" on Scope
Symptom: BadMethodCallException: Call to undefined method Model::xxx()
Cause: The scope method is not defined with the scope prefix.
Fix: Scope methods must be prefixed with scope (camelCase):
// Define
public function scopeActive($query) // Good: Correct
public function active($query) // Bad: Wrong — not a scope
// Usage
Model::active(); // Calls scopeActive()
Timestamps Not Being Set
Symptom: created_at and updated_at are not populated.
Cause 1: Timestamps are disabled on the model.
Fix:
protected bool $timestamps = true; // Ensure this is true
Cause 2: Custom column names don't match your database schema.
Fix:
protected ?string $createdAtColumn = 'date_created'; // Match your schema
protected ?string $updatedAtColumn = 'date_modified';
Getting Help
If you can't find a solution here:
- Check the API Reference for method signatures
- Review the Examples for working code
- Open an issue on GitHub