PHPackages                             charleslightjarvis/laravel-todo - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. charleslightjarvis/laravel-todo

ActiveLibrary[Database &amp; ORM](/categories/database)

charleslightjarvis/laravel-todo
===============================

A Laravel package to attach todo lists to any Eloquent model.

v1.0.1(1mo ago)13[2 PRs](https://github.com/CharlesLightjarvis/laravel-todo/pulls)MITPHPPHP ^8.2CI passing

Since Apr 23Pushed 1mo agoCompare

[ Source](https://github.com/CharlesLightjarvis/laravel-todo)[ Packagist](https://packagist.org/packages/charleslightjarvis/laravel-todo)[ Docs](https://github.com/charleslightjarvis/laravel-todo)[ GitHub Sponsors](https://github.com/laravel-todo)[ RSS](/packages/charleslightjarvis-laravel-todo/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (1)Dependencies (14)Versions (5)Used By (0)

Laravel Todo
============

[](#laravel-todo)

[![Latest Version on Packagist](https://camo.githubusercontent.com/272cc752fe74f0aa0e84194782f6df15698887005b2d6a1b467f4831f186ca0a/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f636861726c65736c696768746a61727669732f6c61726176656c2d746f646f2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/charleslightjarvis/laravel-todo)[![Total Downloads](https://camo.githubusercontent.com/bc0cc5e9de69a959ee731daff641fdec27f0a5243c3bbb57c8ab5bad9f701c3b/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f636861726c65736c696768746a61727669732f6c61726176656c2d746f646f2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/charleslightjarvis/laravel-todo)[![License](https://camo.githubusercontent.com/0aff17915915f361414c2c0724c547d39d6b41e39b2a855e508fb70a40b560b1/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f636861726c65736c696768746a61727669732f6c61726176656c2d746f646f2e7376673f7374796c653d666c61742d737175617265)](LICENSE.md)

Attach todo lists to any Eloquent model in your Laravel application.

The Problem
-----------

[](#the-problem)

In a Laravel application, multiple entities (`User`, `Project`, `Team`, `Invoice`...) often need their own todo list. Without a package, you have to:

- Create a separate table for each entity type (`user_todos`, `project_todos`, `team_todos`...)
- Duplicate models, scopes, and relationships
- Maintain the same logic across multiple places
- No unified API to interact with todos

The Solution
------------

[](#the-solution)

`laravel-todo` lets you attach todos to **any Eloquent model** with a single trait. One table, one logic, every model.

- ✅ Attach todos to `User`, `Project`, `Team`, `Invoice` — anything
- ✅ Fluent API via Trait and Facade
- ✅ Built-in scopes: `pending`, `completed`, `overdue`, `highPriority`, `dueToday`
- ✅ Polymorphic creator support (tracks who created the todo)
- ✅ Zero duplication

Features
--------

[](#features)

- ✅ Polymorphic relationship – attach todos to any model (`User`, `Project`, `Team`, etc.)
- ✅ Fluent API via Facade or Trait
- ✅ Built-in scopes: `pending()`, `completed()`, `overdue()`, `highPriority()`, `dueToday()`
- ✅ Status management: `pending`, `in_progress`, `completed`, `cancelled`
- ✅ Priority levels: `low`, `medium`, `high`
- ✅ Tracks who created each todo (polymorphic `creator` relation)
- ✅ Zero UI – backend only, integrate however you want

Requirements
------------

[](#requirements)

- PHP 8.2 or higher
- Laravel 11.0 or higher

Installation
------------

[](#installation)

Install the package via Composer:

```
composer require charleslightjarvis/laravel-todo
```

Publish the migration file:

```
php artisan vendor:publish --tag="todo-migrations"
```

Run the migrations:

```
php artisan migrate
```

Publish the configuration file (optional):

```
php artisan vendor:publish --tag="todo-config"
```

Configuration
-------------

[](#configuration)

The config file `config/todo.php` allows you to customize:

```
return [
    'prune_after_days' => 30,

    'models' => [
        'todo' => CharlesLightjarvis\Todo\Models\Todo::class,
    ],

    'todo_morph_key' => 'todoable_id',
];
```

Usage
-----

[](#usage)

### 1. Add the trait to your model

[](#1-add-the-trait-to-your-model)

Add `HasTodos` to any Eloquent model you want to attach todos to:

```
use CharlesLightjarvis\Todo\Traits\HasTodos;

class User extends Model
{
    use HasTodos;
}

class Project extends Model
{
    use HasTodos;
}
```

### 2. Creating todos via the Trait

[](#2-creating-todos-via-the-trait)

Use the `todos()` relation directly on any model that uses `HasTodos`:

```
$user = User::find(1);

// Create a todo on the model
$todo = $user->todos()->create([
    'title'    => 'Buy groceries',
    'priority' => 'high',
    'due_at'   => now()->addDays(2),
]);

// Create with addTodo() — optionally assign a creator
$todo = $user->addTodo([
    'title'    => 'Finish the report',
    'priority' => 'medium',
], $creator);
```

### 3. Querying todos via the Trait

[](#3-querying-todos-via-the-trait)

All built-in scopes are available directly on the relation:

```
$user->todos()->pending()->get();
$user->todos()->inProgress()->get();
$user->todos()->completed()->get();
$user->todos()->cancelled()->get();

$user->todos()->highPriority()->get();
$user->todos()->overdue()->get();
$user->todos()->dueToday()->get();

// Scopes can be chained
$user->todos()->pending()->highPriority()->get();
```

### 4. Creating and querying todos via the Facade

[](#4-creating-and-querying-todos-via-the-facade)

The `Todo` facade provides a model-agnostic API — useful when you do not have a direct reference to the owning model instance:

```
use CharlesLightjarvis\Todo\Facades\Todo;

// Create a todo for any model
$todo = Todo::createFor($user, [
    'title'    => 'Fix navigation bug',
    'priority' => 'high',
    'due_at'   => now()->addWeek(),
]);

// Scope queries to a specific model
Todo::for($user)->pending()->get();
Todo::for($user)->highPriority()->get();
Todo::for($user)->overdue()->get();

// Count
Todo::for($user)->count();
Todo::for($user)->pending()->count();
Todo::for($user)->completed()->count();
```

### 5. Completing and cancelling todos

[](#5-completing-and-cancelling-todos)

Both methods are ownership-aware — they silently return `false` if the todo does not belong to the model:

```
// Complete a todo
$user->completeTodo($todo);

// After completion
$todo->refresh();
$todo->status->value;  // 'completed'
$todo->completed_at;   // Carbon timestamp

// Cancel a todo
$user->cancelTodo($todo);

$todo->refresh();
$todo->status->value;  // 'cancelled'

// Another user cannot complete a todo they don't own
$otherUser->completeTodo($todo); // returns false, status unchanged
```

### 6. Accessing todo relations

[](#6-accessing-todo-relations)

```
// All todos attached to the model
$user->todos;

// All todos created by the model (via the creator relation)
$user->createdTodos;
```

### 7. Tracking who created a todo

[](#7-tracking-who-created-a-todo)

```
// Via addTodo — pass the creator as the second argument
$todo = $project->addTodo(['title' => 'Review PR'], auth()->user());

// Or set creator fields manually
$todo = $project->todos()->create([
    'title'        => 'Review PR',
    'creator_type' => $user->getMorphClass(),
    'creator_id'   => $user->id,
]);

// Resolve the creator
$todo->creator; // returns the creator model
```

Available Scopes
----------------

[](#available-scopes)

ScopeDescription`pending()`Status = `pending``inProgress()`Status = `in_progress``completed()`Status = `completed``cancelled()`Status = `cancelled``overdue()`Not completed + `due_at` in the past`highPriority()`Priority = `high``dueToday()``due_at` is todayEnums
-----

[](#enums)

The package provides two enums for type safety:

```
use CharlesLightjarvis\Todo\Enums\TodoStatusEnum;
use CharlesLightjarvis\Todo\Enums\TodoPriorityEnum;

// Status values
TodoStatusEnum::PENDING->value;      // 'pending'
TodoStatusEnum::IN_PROGRESS->value;  // 'in_progress'
TodoStatusEnum::COMPLETED->value;    // 'completed'
TodoStatusEnum::CANCELLED->value;    // 'cancelled'

// Priority values
TodoPriorityEnum::LOW->value;    // 'low'
TodoPriorityEnum::MEDIUM->value; // 'medium'
TodoPriorityEnum::HIGH->value;   // 'high'
```

Testing
-------

[](#testing)

```
composer test
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

Contributions are welcome! Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

Security
--------

[](#security)

If you discover any security-related issues, please email  instead of using the issue tracker.

Credits
-------

[](#credits)

- [Charles Lightjarvis](https://github.com/CharlesLightjarvis)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance90

Actively maintained with recent releases

Popularity5

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity49

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

47d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/927de50456605047e986904092b57fca68818c660d15529adbaab764e76be63c?d=identicon)[CharlesLightjarvis](/maintainers/CharlesLightjarvis)

---

Top Contributors

[![CharlesLightjarvis](https://avatars.githubusercontent.com/u/118352168?v=4)](https://github.com/CharlesLightjarvis "CharlesLightjarvis (5 commits)")

---

Tags

eloquentlaravelpackagephppolymorphictask-managementtodolaraveleloquenttasktodo

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/charleslightjarvis-laravel-todo/health.svg)

```
[![Health](https://phpackages.com/badges/charleslightjarvis-laravel-todo/health.svg)](https://phpackages.com/packages/charleslightjarvis-laravel-todo)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3325.1M337](/packages/psalm-plugin-laravel)[spatie/laravel-health

Monitor the health of a Laravel application

88011.3M149](/packages/spatie-laravel-health)[kirschbaum-development/eloquent-power-joins

The Laravel magic applied to joins.

1.6k29.9M42](/packages/kirschbaum-development-eloquent-power-joins)[watson/validating

Eloquent model validating trait.

9743.4M53](/packages/watson-validating)[clickbar/laravel-magellan

This package provides functionality for working with the postgis extension in Laravel.

436834.4k1](/packages/clickbar-laravel-magellan)[laravel/ai

The official AI SDK for Laravel.

9782.1M153](/packages/laravel-ai)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
