CI4 Playground v4.7.3
한국어문서
유저 생성 (beforeInsert 콜백)

비밀번호를 입력하면 beforeInsert 콜백이 자동으로 password_hash()를 적용합니다.

유저 목록 (afterFind 콜백 — 비밀번호 마스킹)

afterFind 콜백이 조회된 모든 레코드의 password 필드를 ••••••••로 치환합니다.

ID 사용자명 이메일 비밀번호 역할 상태
1 admin admin@example.com •••••••• admin 활성
2 editor editor@example.com •••••••• editor 활성
3 honggil honggil@example.com •••••••• user 활성
DB에는 bcrypt 해시가 저장되어 있으며, afterFind 콜백이 화면 출력 전 ••••••••로 치환합니다.
UserCallbackModel — 콜백 등록
app/Models/UserCallbackModel.php
class UserCallbackModel extends Model
{
    protected $table          = 'users_demo';
    protected $allowedFields  = ['username', 'email', 'password', 'role', 'status'];
    protected $useTimestamps  = true;
    protected $useSoftDeletes = true;
    protected $allowCallbacks = true;   // 콜백 활성화 (필수!)

    // 삽입·수정 전 실행되는 콜백 목록
    protected $beforeInsert = ['hashPassword'];
    protected $beforeUpdate = ['hashPassword'];

    // 조회 후 실행되는 콜백 목록
    protected $afterFind    = ['maskPassword'];
}
beforeInsert / beforeUpdate — 비밀번호 해싱
protected function hashPassword(array $data): array
{
    // $data['data'] 에 실제 저장될 배열이 담김
    if (! empty($data['data']['password'])) {
        $data['data']['password'] = password_hash(
            $data['data']['password'],
            PASSWORD_DEFAULT   // bcrypt
        );
    }
    return $data;
}
포인트: 콜백은 반드시 $data 배열을 반환해야 합니다. 수정하지 않은 값도 그대로 반환해야 데이터 손실이 없습니다.
afterFind — 비밀번호 마스킹
protected function maskPassword(array $data): array
{
    if (isset($data['data'])) {
        if (is_array($data['data'])
            && isset($data['data']['id'])) {
            // 단일 레코드 (find / first)
            $data['data']['password'] = '••••••••';
        } elseif (is_array($data['data'])) {
            // 목록 (findAll)
            foreach ($data['data'] as &$row) {
                if (is_array($row)) {
                    $row['password'] = '••••••••';
                }
            }
        }
    }
    return $data;
}
포인트: afterFind는 단건/목록 모두 호출됩니다. $data['singleton']로 단건 여부를 구분할 수도 있습니다.
사용 가능한 콜백 종류
콜백실행 시점$data 키
beforeInsertinsert() 실행 전data, result
afterInsertinsert() 실행 후id, data, result
beforeUpdateupdate() 실행 전id, data, result
afterUpdateupdate() 실행 후id, data, result
afterFindfind*/first 실행 후data, singleton, id
beforeDeletedelete() 실행 전id, purge
afterDeletedelete() 실행 후id, data, purge, result