'boolean', 'synced_at' => 'datetime', ]; } public function preregistrationPage(): BelongsTo { return $this->belongsTo(PreregistrationPage::class); } /** * @param string|null $value */ public function setPhoneAttribute(mixed $value): void { if ($value === null) { $this->attributes['phone'] = null; return; } if (! is_string($value)) { $this->attributes['phone'] = null; return; } $trimmed = trim($value); if ($trimmed === '') { $this->attributes['phone'] = null; return; } $normalized = app(PhoneNumberNormalizer::class)->normalizeToE164($trimmed); $this->attributes['phone'] = $normalized; } /** * Phones are stored as E.164 (e.g. +31612345678). Legacy rows may still be digits-only. */ public function phoneDisplay(): ?string { $phone = $this->phone; if ($phone === null || $phone === '') { return null; } $p = (string) $phone; if (str_starts_with($p, '+')) { return $p; } return preg_match('/^\d{8,15}$/', $p) === 1 ? '+'.$p : $p; } public function scopeSearch(Builder $query, ?string $term): Builder { if ($term === null || $term === '') { return $query; } $like = '%'.$term.'%'; return $query->where(function (Builder $q) use ($like): void { $q->where('first_name', 'like', $like) ->orWhere('last_name', 'like', $like) ->orWhere('email', 'like', $like) ->orWhere('phone', 'like', $like); }); } }