JCC Express

JCC Eloquent ORM

Mutators

Introduction

JCC-Eloquent supports attribute mutation at the model level through:

  • method-based mutators and accessors (setXAttribute, getXAttribute)
  • the attributes() map with get / set handlers

These run when you assign values through model properties, fill(...), or call getAttribute(...) / setAttribute(...).


Method-based mutators

Use set{Studly}Attribute to transform values before they are stored in _attributes.

TypeScript
import { Model } from "jcc-express-mvc/Eloquent";
import { bcrypt } from "jcc-express-mvc/Security";

export class User extends Model {
  protected fillable = ["name", "email", "password"];

  setPasswordAttribute(value: string) {
    this._attributes["password"] = bcrypt(value);
  }
}

When you set user.password = "secret" or call user.fill({ password: "secret" }), this mutator is used.


Method-based accessors

Use get{Studly}Attribute to customize values when reading attributes.

TypeScript
import { Model } from "jcc-express-mvc/Eloquent";

export class User extends Model {
  getNameAttribute(value: string) {
    return value ? value.trim() : value;
  }
}

getAttribute("name") and property access (user.name) will use this accessor.


attributes() getter/setter handlers

For per-attribute definitions, override attributes() and return get / set handlers.

TypeScript
import { Model } from "jcc-express-mvc/Eloquent";

export class User extends Model {
  protected attributes() {
    return {
      name: {
        set: (value: string) => {
          this._attributes["name"] = value.trim();
        },
        get: (value: string) => value?.toUpperCase(),
      },
    };
  }
}

If both method-based and attributes() handlers exist for the same key, method-based accessors/mutators are checked first.


How mutators are triggered

Mutators/accessors run through model internals:

  • setAttribute(key, value) checks set{Studly}Attribute first, then attributes()[key].set
  • getAttribute(key) checks get{Studly}Attribute first, then attributes()[key].get
  • fill(...) uses setAttribute(...), so mutators apply there too

Notes on casts

Model casts and mutators can be used together:

  • mutator transforms incoming values
  • casts normalize storage/read behavior for configured fields

Keep transformations predictable to avoid double-processing the same value.