Overview
The ActivityExercise model tracks physical activities and exercise sessions for users in Health Manager. It supports detailed exercise logging with duration tracking, descriptions, and file attachments through polymorphic relationships.
Namespace
App \ Models \ ActivityExercise
Class Declaration
class ActivityExercise extends Model
Database Schema
The activity_exercises table includes the following columns:
Primary key, auto-incrementing
Foreign key referencing users table (cascades on delete)
Exercise or activity title
Date and time when the activity was performed
Optional detailed description of the activity
Duration of the activity in minutes
Legacy file path (deprecated - use attachments relationship instead)
Record creation timestamp
Record last update timestamp
Fillable Attributes
These attributes can be mass assigned:
ID of the user who performed this activity
Activity title (e.g., “Morning Run”, “Gym Workout”, “Yoga Session”)
Date and time of the activity in Y-m-d H:i:s format
Detailed description, notes, or workout details
Duration in minutes (e.g., 30, 45, 60)
Legacy field for single file attachment (use attachments relationship for multiple files)
Casts
[
'date' => 'datetime' ,
]
The date attribute is automatically cast to a Carbon datetime instance.
Relationships
user()
Belongs to relationship with the User model.
Show Relationship Details
One-to-many inverse relationship
Foreign key on activity_exercises table
public function user () : BelongsTo
{
return $this -> belongsTo ( User :: class );
}
Example Usage:
$activity = ActivityExercise :: find ( 1 );
$userName = $activity -> user -> name ;
attachments()
Polymorphic relationship for file attachments (e.g., workout photos, GPS tracks, screenshots).
Show Relationship Details
One-to-many polymorphic relationship
Related to Attachment model
Polymorphic relationship name
Stores ‘App\Models\ActivityExercise’
public function attachments () : MorphMany
{
return $this -> morphMany ( Attachment :: class , 'model' );
}
Example Usage:
$activity = ActivityExercise :: find ( 1 );
// Get all attachments
$files = $activity -> attachments ;
// Add new attachment
$activity -> attachments () -> create ([
'file_path' => 'activities/workout-photo.jpg' ,
'file_name' => 'workout-photo.jpg' ,
]);
Usage Examples
Creating Exercise Activities
use App\Models\ ActivityExercise ;
use Carbon\ Carbon ;
// Create a simple activity
$activity = ActivityExercise :: create ([
'user_id' => auth () -> id (),
'title' => 'Morning Run' ,
'date' => now (),
'duration_minutes' => 30 ,
'description' => '5K run in the park' ,
]);
echo "Activity logged: { $activity -> title } - { $activity -> duration_minutes } minutes" ;
Creating Activity with Attachments
$activity = ActivityExercise :: create ([
'user_id' => auth () -> id (),
'title' => 'HIIT Workout' ,
'date' => Carbon :: parse ( '2026-03-05 18:00:00' ),
'duration_minutes' => 45 ,
'description' => '4 rounds: burpees, squats, push-ups, mountain climbers' ,
]);
// Add workout photos
$activity -> attachments () -> createMany ([
[
'file_path' => 'storage/activities/before-workout.jpg' ,
'file_name' => 'Before Workout.jpg' ,
],
[
'file_path' => 'storage/activities/after-workout.jpg' ,
'file_name' => 'After Workout.jpg' ,
],
]);
Querying Activities
// Get all activities for current user
$allActivities = ActivityExercise :: where ( 'user_id' , auth () -> id ())
-> orderBy ( 'date' , 'desc' )
-> get ();
// Get recent activities
$recent = ActivityExercise :: where ( 'user_id' , auth () -> id ())
-> where ( 'date' , '>=' , now () -> subDays ( 7 ))
-> orderBy ( 'date' , 'desc' )
-> get ();
// Get activities with attachments
$withFiles = ActivityExercise :: with ( 'attachments' )
-> where ( 'user_id' , auth () -> id ())
-> get ();
// Get activities for specific date range
$marchActivities = ActivityExercise :: where ( 'user_id' , auth () -> id ())
-> whereBetween ( 'date' , [
Carbon :: parse ( '2026-03-01' ),
Carbon :: parse ( '2026-03-31' )
])
-> orderBy ( 'date' , 'asc' )
-> get ();
Calculating Activity Statistics
// Total exercise time this month
$totalMinutes = ActivityExercise :: where ( 'user_id' , auth () -> id ())
-> whereMonth ( 'date' , now () -> month )
-> sum ( 'duration_minutes' );
echo "Total exercise time: { $totalMinutes } minutes (" . round ( $totalMinutes / 60 , 1 ) . " hours)" ;
// Average duration
$avgDuration = ActivityExercise :: where ( 'user_id' , auth () -> id ())
-> avg ( 'duration_minutes' );
echo "Average workout duration: " . round ( $avgDuration ) . " minutes" ;
// Activity count by period
$thisWeek = ActivityExercise :: where ( 'user_id' , auth () -> id ())
-> whereBetween ( 'date' , [ now () -> startOfWeek (), now () -> endOfWeek ()])
-> count ();
$thisMonth = ActivityExercise :: where ( 'user_id' , auth () -> id ())
-> whereMonth ( 'date' , now () -> month )
-> count ();
echo "Activities: { $thisWeek } this week, { $thisMonth } this month" ;
Filtering by Activity Type
// Find running activities
$runs = ActivityExercise :: where ( 'user_id' , auth () -> id ())
-> where ( 'title' , 'like' , '%run%' )
-> orderBy ( 'date' , 'desc' )
-> get ();
// Find gym workouts
$gymWorkouts = ActivityExercise :: where ( 'user_id' , auth () -> id ())
-> where ( 'title' , 'like' , '%gym%' )
-> orWhere ( 'title' , 'like' , '%workout%' )
-> orderBy ( 'date' , 'desc' )
-> get ();
// Find activities by minimum duration
$longWorkouts = ActivityExercise :: where ( 'user_id' , auth () -> id ())
-> where ( 'duration_minutes' , '>=' , 60 )
-> orderBy ( 'duration_minutes' , 'desc' )
-> get ();
Updating Activities
$activity = ActivityExercise :: find ( 1 );
$activity -> update ([
'title' => 'Evening Run - Updated' ,
'duration_minutes' => 35 ,
'description' => 'Extended the route by 1K' ,
]);
Filtering by Date
use Carbon\ Carbon ;
// Today's activities
$today = ActivityExercise :: whereDate ( 'date' , today ())
-> where ( 'user_id' , auth () -> id ())
-> get ();
// This week's activities
$thisWeek = ActivityExercise :: whereBetween ( 'date' , [
now () -> startOfWeek (),
now () -> endOfWeek ()
])
-> where ( 'user_id' , auth () -> id ())
-> get ();
// Last 30 days
$last30Days = ActivityExercise :: where ( 'user_id' , auth () -> id ())
-> where ( 'date' , '>=' , now () -> subDays ( 30 ))
-> orderBy ( 'date' , 'desc' )
-> get ();
Activity Streaks
// Calculate current streak
function calculateStreak ( $userId )
{
$activities = ActivityExercise :: where ( 'user_id' , $userId )
-> whereDate ( 'date' , '>=' , now () -> subDays ( 90 ))
-> orderBy ( 'date' , 'desc' )
-> get ()
-> groupBy ( function ( $activity ) {
return $activity -> date -> format ( 'Y-m-d' );
});
$streak = 0 ;
$currentDate = now ();
while ( $activities -> has ( $currentDate -> format ( 'Y-m-d' ))) {
$streak ++ ;
$currentDate -> subDay ();
}
return $streak ;
}
$streak = calculateStreak ( auth () -> id ());
echo "Current streak: { $streak } days" ;
Working with Relationships
// Eager load relationships
$activities = ActivityExercise :: with ([ 'user' , 'attachments' ])
-> where ( 'date' , '>=' , now () -> subDays ( 7 ))
-> get ();
foreach ( $activities as $activity ) {
echo "{ $activity -> user -> name }: { $activity -> title } - { $activity -> duration_minutes } min \n " ;
echo "Attachments: { $activity -> attachments -> count ()} \n " ;
}
Charting Activity Data
// Get weekly activity data for chart
$weeklyData = [];
for ( $i = 6 ; $i >= 0 ; $i -- ) {
$date = now () -> subDays ( $i );
$totalMinutes = ActivityExercise :: where ( 'user_id' , auth () -> id ())
-> whereDate ( 'date' , $date )
-> sum ( 'duration_minutes' );
$weeklyData [] = [
'date' => $date -> format ( 'Y-m-d' ),
'day' => $date -> format ( 'l' ),
'minutes' => $totalMinutes ,
];
}
return response () -> json ( $weeklyData );
Deleting Activities
$activity = ActivityExercise :: find ( 1 );
// Delete activity with attachments
$activity -> attachments () -> delete ();
$activity -> delete ();
// Delete old activities (e.g., older than 2 years)
ActivityExercise :: where ( 'user_id' , auth () -> id ())
-> where ( 'date' , '<' , now () -> subYears ( 2 ))
-> delete ();
JSON Serialization Example
$activity = ActivityExercise :: with ([ 'user' , 'attachments' ]) -> find ( 1 );
return response () -> json ( $activity );
Output:
{
"id" : 1 ,
"user_id" : 5 ,
"title" : "Morning Run" ,
"date" : "2026-03-05T07:00:00.000000Z" ,
"description" : "5K run in the park" ,
"duration_minutes" : 30 ,
"file_path" : null ,
"created_at" : "2026-03-05T07:30:00.000000Z" ,
"updated_at" : "2026-03-05T07:30:00.000000Z" ,
"user" : {
"id" : 5 ,
"name" : "John Doe" ,
"email" : "[email protected] " ,
"username" : "johndoe"
},
"attachments" : [
{
"id" : 1 ,
"model_type" : "App \\ Models \\ ActivityExercise" ,
"model_id" : 1 ,
"file_path" : "storage/activities/workout-photo.jpg" ,
"file_name" : "Workout Photo.jpg" ,
"created_at" : "2026-03-05T07:31:00.000000Z" ,
"updated_at" : "2026-03-05T07:31:00.000000Z"
}
]
}
API Response Example for Activity Dashboard
// Controller method to get activity summary
public function getActivitySummary ()
{
$userId = auth () -> id ();
$thisWeek = ActivityExercise :: where ( 'user_id' , $userId )
-> whereBetween ( 'date' , [ now () -> startOfWeek (), now () -> endOfWeek ()])
-> get ();
$thisMonth = ActivityExercise :: where ( 'user_id' , $userId )
-> whereMonth ( 'date' , now () -> month )
-> get ();
return response () -> json ([
'this_week' => [
'count' => $thisWeek -> count (),
'total_minutes' => $thisWeek -> sum ( 'duration_minutes' ),
],
'this_month' => [
'count' => $thisMonth -> count (),
'total_minutes' => $thisMonth -> sum ( 'duration_minutes' ),
],
'recent_activities' => ActivityExercise :: where ( 'user_id' , $userId )
-> orderBy ( 'date' , 'desc' )
-> limit ( 5 )
-> get (),
]);
}
Response:
{
"this_week" : {
"count" : 4 ,
"total_minutes" : 180
},
"this_month" : {
"count" : 12 ,
"total_minutes" : 540
},
"recent_activities" : [
{
"id" : 1 ,
"user_id" : 5 ,
"title" : "Morning Run" ,
"date" : "2026-03-05T07:00:00.000000Z" ,
"duration_minutes" : 30
},
{
"id" : 2 ,
"user_id" : 5 ,
"title" : "Gym Workout" ,
"date" : "2026-03-04T18:00:00.000000Z" ,
"duration_minutes" : 60
}
]
}
Traits Used
HasFactory - Enables model factories for testing and seeding