abduns / laravel-fit-reader
A focused Laravel 12 package to read Garmin .fit activity files.
Installs: 3
Dependents: 0
Suggesters: 0
Security: 0
Stars: 1
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/abduns/laravel-fit-reader
Requires
- php: ^8.2
- illuminate/http: ^12.0
- illuminate/support: ^12.0
Requires (Dev)
- orchestra/testbench: ^10.0
- pestphp/pest: ^3.0
- pestphp/pest-plugin-laravel: ^3.0
README
A focused, developer-friendly Laravel package to read and parse Garmin .fit activity files.
This package provides a native PHP implementation for parsing FIT files, converting raw data into easy-to-use Data Transfer Objects (DTOs). It's perfect for building fitness apps, training logs, or analysis tools without external binary dependencies.
โจ Features
- ๐ Simple API: Use the Facade or Dependency Injection to read files.
- ๐ฆ DTO Support: Work with typed objects (
FitActivity,FitRecord,FitLap) instead of raw arrays. - ๐ Laravel Integration: Built specifically for Laravel 12+.
- โ๏ธ Configurable: Customize parsing options via a config file.
โ Requirements
- PHP 8.2+
- Laravel 12.x
๐ฆ Installation
You can install the package via composer:
composer require abduns/laravel-fit-reader
You can publish the config file with:
php artisan vendor:publish --tag="fit-reader-config"
๐ Usage
Reading a File
You can easily read a .fit file using the FitReader facade.
use Dunn\FitReader\Facades\FitReader; // Read from a local path $activity = FitReader::fromPath(storage_path('app/activities/run.fit'));
Working with the Data
The fromPath method returns a Dunn\FitReader\DTO\FitActivity object. Here is how you can access the data:
Activity Summary
echo "Start Time: " . $activity->startTime->format('Y-m-d H:i:s'); echo "Total Distance: " . $activity->totalDistanceMeters . " meters"; echo "Total Duration: " . $activity->totalDurationSeconds . " seconds"; // Sport Type (new in v1.2.0) echo "Sport: " . $activity->getSportName(); // e.g., "running", "cycling", "swimming" echo "Sport ID: " . $activity->sport; // Raw sport type ID // Device Metadata echo "Manufacturer ID: " . $activity->manufacturer; echo "Product ID: " . $activity->product; echo "Serial Number: " . $activity->serialNumber;
Records (Time Series Data)
Access the stream of data points (heart rate, speed, location, etc.) via the records collection.
foreach ($activity->records as $record) { // $record is an instance of Dunn\FitReader\DTO\FitRecord echo $record->timestamp->format('H:i:s') . " - "; echo "HR: " . $record->heartRateBpm . " bpm, "; echo "Speed: " . $record->speedMps . " m/s"; // Available properties: // $record->latitude // $record->longitude // $record->altitudeMeters // $record->heartRateBpm // $record->cadenceRpm // $record->speedMps // $record->powerWatts }
Laps
Access lap data via the laps collection.
foreach ($activity->laps as $index => $lap) { // $lap is an instance of Dunn\FitReader\DTO\FitLap echo "Lap " . ($index + 1) . ": "; echo $lap->totalDistanceMeters . "m in " . $lap->totalDurationSeconds . "s"; echo "Avg HR: " . $lap->averageHeartRateBpm; }
Handling Uploads in a Controller
Here is a practical example of handling a file upload in a Laravel Controller.
use Illuminate\Http\Request; use Dunn\FitReader\Facades\FitReader; class ActivityController extends Controller { public function store(Request $request) { $request->validate([ 'activity_file' => 'required|file', ]); $file = $request->file('activity_file'); // Parse the uploaded file directly $activity = FitReader::fromUploadedFile($file); return response()->json([ 'distance' => $activity->totalDistanceMeters, 'duration' => $activity->totalDurationSeconds, 'records_count' => $activity->records->count(), ]); } }
Exporting Data
New in v1.2.0: You can export activity data as raw arrays or JSON for easy storage or API responses.
// Export entire activity as array $array = $activity->toArray(); // Export as JSON $json = $activity->toJson(); // Export with pretty print $prettyJson = $activity->toJson(JSON_PRETTY_PRINT); // Export individual records foreach ($activity->records as $record) { $recordArray = $record->toArray(); $recordJson = $record->toJson(); } // Export individual laps foreach ($activity->laps as $lap) { $lapArray = $lap->toArray(); $lapJson = $lap->toJson(); }
Detecting Activity Type
New in v1.2.0: Automatically detect what type of activity was recorded.
$activity = FitReader::fromPath('/path/to/run.fit'); if ($activity->getSportName() === 'running') { echo "This is a running activity!"; // Access running-specific data echo "Average pace: " . /* calculate from records */; } elseif ($activity->getSportName() === 'cycling') { echo "This is a cycling activity!"; } // Supported sport types include: // running, cycling, swimming, walking, hiking, // fitness_equipment, multisport, and 40+ more
Dependency Injection
If you prefer dependency injection over Facades, you can type-hint the contract.
use Dunn\FitReader\Contracts\FitReader; class ImportActivityJob { public function __construct( protected FitReader $fitReader ) {} public function handle() { $activity = $this->fitReader->fromPath('/path/to/file.fit'); // ... } }
๐ง Configuration
This is the contents of the published config file:
return [ 'units' => [ 'raw_values' => false, // Set to true if you want raw values instead of converted units ], ];
๐งช Testing
composer test
๐ Changelog
Please see CHANGELOG for more information on what has changed recently.
๐ Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
๐ Versioning
This package follows Semantic Versioning. For information on how to release new versions, see RELEASING.md.
๐ License
The MIT License (MIT). Please see License File for more information.