Skip to main content

Overview

The PersonalData model stores additional personal information for users in the NutriFit system. This data extends the base User model with demographics and contact information. Namespace: App\Models\PersonalData Extends: Illuminate\Database\Eloquent\Model Table: personal_data Note: PersonalData is automatically eager-loaded on the User model via $with = ['personalData'].

Fillable Attributes

user_id
integer
required
Foreign key to the User model (one-to-one relationship)
cedula
string
National identification number (e.g., “0401234567” for Ecuadorian CI)
phone
string
Contact phone number
address
string
Physical address
birth_date
date
Date of birth (cast to date)
gender
string
Gender identifier (e.g., “masculino”, “femenino”, “otro”)
profile_photo
string
Path to profile photo in storage (relative path, e.g., “profile-photos/abc123.jpg”)

Casts

The model automatically casts:
  • birth_datedate

Appended Attributes

The following computed attributes are automatically appended to JSON/array serialization:
  • age - Calculated from birth_date

Relationships

BelongsTo

user()
BelongsTo
Returns the user this personal data belongs to (User model)
$personalData->user->email; // Access the associated user

Accessor Methods

getAgeAttribute()

public function getAgeAttribute(): ?int
Calculates the user’s age in years based on their birth date. Returns: Age in years, or null if birth_date is not set. Usage:
$user = User::find(1);
echo $user->personalData->age; // 28 (automatically calculated)

// Also available in JSON
$user->toArray();
// [
//   'personal_data' => [
//     'birth_date' => '1998-05-15',
//     'age' => 28,  // Automatically appended
//   ]
// ]
Implementation: Uses Carbon’s age property to calculate years between birth_date and today.

Usage Examples

Creating Personal Data

use App\Models\User;
use App\Models\PersonalData;

// Create user first
$user = User::create([
    'name' => 'María González',
    'email' => '[email protected]',
    'password' => bcrypt('password'),
    'role_id' => 3,
    'user_state_id' => 1,
]);

// Add personal data
$personalData = PersonalData::create([
    'user_id' => $user->id,
    'cedula' => '0401234567',
    'phone' => '0987654321',
    'address' => 'Av. Principal 123, Quito',
    'birth_date' => '1995-08-15',
    'gender' => 'femenino',
]);

Accessing Personal Data

// PersonalData is automatically loaded
$user = User::find(1);

// Access personal data directly (no additional query)
echo $user->personalData->phone;
echo $user->personalData->age; // Calculated automatically
echo $user->personalData->birth_date->format('d/m/Y'); // 15/08/1995

Uploading Profile Photo

use Illuminate\Support\Facades\Storage;

// Handle file upload
if ($request->hasFile('profile_photo')) {
    // Delete old photo if exists
    if ($user->personalData?->profile_photo) {
        Storage::disk('public')->delete($user->personalData->profile_photo);
    }
    
    // Store new photo
    $path = $request->file('profile_photo')->store('profile-photos', 'public');
    
    // Update personal data
    $user->personalData->update([
        'profile_photo' => $path,
    ]);
}

// Get profile photo URL using User helper method
$photoUrl = $user->profilePhotoUrl(); // Uses this PersonalData field

Updating Personal Data

$user = User::find(1);

// Update via relationship
$user->personalData->update([
    'phone' => '0991234567',
    'address' => 'Nueva dirección 456, Guayaquil',
]);

// Or find and update directly
PersonalData::where('user_id', $user->id)->update([
    'cedula' => '0409876543',
]);

Querying by Personal Data

// Find users by cedula
$user = User::whereHas('personalData', function ($query) use ($cedula) {
    $query->where('cedula', $cedula);
})->first();

// Find users within age range
$users = User::whereHas('personalData', function ($query) {
    $query->whereNotNull('birth_date')
          ->whereRaw('YEAR(CURDATE()) - YEAR(birth_date) BETWEEN 25 AND 35');
})->get();

// Get users with profile photos
$usersWithPhotos = User::whereHas('personalData', function ($query) {
    $query->whereNotNull('profile_photo');
})->get();

Validating Personal Data

// Validation rules example
$rules = [
    'cedula' => 'required|string|size:10|unique:personal_data,cedula,' . $user->id . ',user_id',
    'phone' => 'required|string|min:10|max:13',
    'address' => 'nullable|string|max:255',
    'birth_date' => 'required|date|before:today|after:1900-01-01',
    'gender' => 'required|in:masculino,femenino,otro',
    'profile_photo' => 'nullable|image|mimes:jpeg,png,jpg|max:2048',
];

$validated = $request->validate($rules);

Calculating Age-Based Metrics

$user = User::with('personalData')->find(1);
$age = $user->personalData->age;

// Age-based recommendations
if ($age < 18) {
    $caloricNeeds = 2000; // Adolescent
} elseif ($age < 65) {
    $caloricNeeds = 1800; // Adult
} else {
    $caloricNeeds = 1600; // Senior
}

// Check if user can register (age requirement)
if ($age < 18) {
    return back()->withErrors('Debe ser mayor de 18 años para registrarse.');
}

Displaying User Profile

$user = User::find(1);
$data = $user->personalData;

// Build profile display
$profile = [
    'name' => $user->name,
    'email' => $user->email,
    'initials' => $user->initials(),
    'photo_url' => $user->profilePhotoUrl(),
    'cedula' => $data->cedula,
    'phone' => $data->phone,
    'address' => $data->address,
    'age' => $data->age,
    'gender' => $data->gender,
    'birth_date' => $data->birth_date?->format('d/m/Y'),
];

Seeding Example

// In a seeder or factory
use App\Models\User;
use App\Models\PersonalData;

User::factory(50)->create()->each(function ($user) {
    PersonalData::create([
        'user_id' => $user->id,
        'cedula' => fake()->numerify('04########'),
        'phone' => fake()->numerify('09########'),
        'address' => fake()->address(),
        'birth_date' => fake()->dateTimeBetween('-65 years', '-18 years'),
        'gender' => fake()->randomElement(['masculino', 'femenino', 'otro']),
    ]);
});

Build docs developers (and LLMs) love