PHPackages                             binary-cats/coordinator - 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. binary-cats/coordinator

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

binary-cats/coordinator
=======================

Schedule and manage resource booking (appointments) in your Laravel app

9.1.0(1y ago)7712MITPHPPHP ^8.0

Since Apr 15Pushed 1y ago2 watchersCompare

[ Source](https://github.com/binary-cats/coordinator)[ Packagist](https://packagist.org/packages/binary-cats/coordinator)[ Docs](https://github.com/binary-cats/coordinator)[ RSS](/packages/binary-cats-coordinator/feed)WikiDiscussions v9.x Synced today

READMEChangelog (3)Dependencies (5)Versions (5)Used By (0)

[![](./resources/images/coordinator.svg)](./resources/images/coordinator.svg)

Coordinator
===========

[](#coordinator)

**Coordinator** is a generic resource booking system for Laravel, built with simplicity in mind. It will allow you to book (or schedule) resources using simple intuitive API.

[![https://github.com/binary-cats/coordinator/actions](https://github.com/binary-cats/coordinator/workflows/Laravel/badge.svg)](https://github.com/binary-cats/coordinator/workflows/Laravel/badge.svg)[![https://github.styleci.io/repos/358098480](https://camo.githubusercontent.com/b317062e055f21a5d2c4023726076dd1658d16a2f0dd606fce0c4ddeeb1c88c1/68747470733a2f2f6769746875622e7374796c6563692e696f2f7265706f732f3335383039383438302f736869656c64)](https://camo.githubusercontent.com/b317062e055f21a5d2c4023726076dd1658d16a2f0dd606fce0c4ddeeb1c88c1/68747470733a2f2f6769746875622e7374796c6563692e696f2f7265706f732f3335383039383438302f736869656c64)[![https://scrutinizer-ci.com/g/binary-cats/coordinator/](https://camo.githubusercontent.com/0561b2b311704f0b4e8b44f81d8c3df7d5ff3743a2eb5e06069df35627f6b2b3/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f62696e6172792d636174732f636f6f7264696e61746f722f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://camo.githubusercontent.com/0561b2b311704f0b4e8b44f81d8c3df7d5ff3743a2eb5e06069df35627f6b2b3/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f62696e6172792d636174732f636f6f7264696e61746f722f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)

The package is built with expectations that you would probably extending it for you own needs, so very few conventions are used. Please make sure to familiarize yourselves with the [concepts](#concepts).

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

[](#installation)

You can install the package via composer:

```
composer require binary-cats/coordinator
```

The Service Provider will automatically register itself and add the following configuration to your Laravel installation:

```
use BinaryCats\Coordinator\Eloquent\Booking;
use Spatie\Period\Boundaries;
use Spatie\Period\Precision;

return [

    /*
    |--------------------------------------------------------------------------
    | Coordinator: Booking Model
    |--------------------------------------------------------------------------
    |
    | The default is `BinaryCats\Coordinator\Eloquent\Booking`.
    | You are likely to extend the class or replace it with your implementation:
    | Model must implement `BinaryCats\Coordinator\Contracts\Booking`
    |
    */

    'booking_model' => Booking::class,

    /*
    |--------------------------------------------------------------------------
    | Booking Period: Precision
    |--------------------------------------------------------------------------
    | Date precision is important if you want to reliably compare two periods:
    | @see https://stitcher.io/blog/comparing-dates
    |
    | Valid options are:
    | YEAR|DAY|HOUR|MINUTE|SECOND
    */

   'precision' => Precision::SECOND(),

   /*
    |--------------------------------------------------------------------------
    | Booking Period: Boundaries
    |--------------------------------------------------------------------------
    | By default, period comparisons are done with included boundaries
    |
    | Valid options are:
    | EXCLUDE_NONE|EXCLUDE_START|EXCLUDE_END|EXCLUDE_ALL
    */

   'boundaries' => Boundaries::EXCLUDE_NONE(),
];
```

To change anything in the setup, you can publish the config file using

```
php artisan vendor:publish --tag=coordinator-config
```

Config file will be published at `config/coordinator.php`:

Migration
---------

[](#migration)

Running the following will publish a single migration for bookings table:

```
php artisan vendor:publish --tag=coordinator-migrations
```

### Concepts

[](#concepts)

The package provides you with a single model: Booking.

#### Booking Model

[](#booking-model)

`Booking` is a single record that ties together bookable resource, like a `Room` or `Table` or `TechSupport` and the model that books the resource. Since the word *book* is present in every word, it may be hard to grasp right away. In essence, `Booking` is a *pivot model*, that has two polymorphic keys: `model` which represents the owner of the relationship and `resource`, representing, well, a resource we want to book.

A simple example, perhaps, will help:

When a *customer* wants to rent an *room*, we have a relationship between a Customer and a Resource they want.

Customer is a `model` and a Room is a `resource` and their relationship is stored as a `Booking`.

#### Availability

[](#availability)

It is not expected that you may want to have overlapping booking of resources, but nothing should stop you from trying!

There are legitimate use cases when you may want to create two bookings and whomever confirms first, gets the slot and the other gets cancelled.

**Coordinator** will not try to force your hand, but that means that you need to implement this logic yorself.

### Usage

[](#usage)

Let's prepare our models. First, the *resource that can be booked*:

```
use BinaryCats\Coordinator\CanBeBooked;
use BinaryCats\Coordinator\Contracts\BookableResource;
use Illuminate\Database\Eloquent\Model;

class Room extends Model implements BookableResource
{
    use CanBeBooked;
}
```

Notice that *Resource* is implementing `BinaryCats\Coordinator\Contracts\BookableResource`.

Now, a model that *books resources*:

```
use BinaryCats\Coordinator\BooksResources;
use BinaryCats\Coordinator\Contracts\CanBookResources;
use Illuminate\Database\Eloquent\Model;

class User extends Model implements CanBookResources
{
    use BooksResources;
}
```

Notice that *Model* is implementing `BinaryCats\Coordinator\Contracts\CanBookResources`.

Just like with notifications, you should not be bound by thinking "it is a user that books something". Any model can be booking any other resource; *a Driver user can be booked by a Delivery* for instance.

**Coordinator** offers fluent interface to create a booking, that can be used on either side of the relation:

```
    $booking = User::first()->createBookingFor(Room::first(), [
        'starts_at' => '2021-01-01 15:45',
        'ends_at' => '2021-01-02 15:45',
    ]);
```

and

```
    $booking = Room::first()->createBookingFor(User::first(), [
        'starts_at' => '2021-01-01 15:45',
        'ends_at' => '2021-01-02 15:45',
    ]);
```

will produce identical result.

### Checking availability

[](#checking-availability)

Bookable resource provides means of checking if it is available or booked at a given moment:

To check if the `Room` is available at a given moment with `isAvailableAt`. The first argument can be any implementation of `DateTimeInterface` that can be converted to `Carbon\Carbon` instance, a string or even a Period:

```
Room::first()->isAvailableAt(new DateTime);
Room::first()->isAvailableAt(Carbon\Carbon::now());
Room::first()->isAvailableAt('2021-01-01 15:45');
Room::first()->isAvailableAt('2021-01-01 3:45 PM CST');
```

To check if the `Room` is available on '2021-01-01', you can use `isAvailableAt`:

```
    // bookings = [
    //      [
    //          ...
    //          'starts_at' => '2021-01-01',
    //          'ends_at' => '2021-01-02',
    //          'cancelled_at' => '2021-04-02'
    //      ]
    // ];
    Room::first()->isAvailableAt('2021-01-01');
    // true;
```

You can pass the second argument to account for the bookings that are canceled:

```
    // bookings = [
    //      [
    //          ...
    //          'starts_at' => '2021-01-01',
    //          'ends_at' => '2021-01-02',
    //          'cancelled_at' => '2021-04-02'
    //      ]
    // ];
    Room::first()->isAvailableAt('2021-01-01', true);
    // false
```

You can check if the `Room` is booked at a given moment with `isBookedAt`:

```
    // bookings = [
    //      [
    //          ...
    //          'starts_at' => '2021-01-01',
    //          'ends_at' => '2021-01-02',
    //          'cancelled_at' => '2021-04-02'
    //      ]
    // ];
    Room::first()->isBookedAt('2021-01-01');
    // false;
```

You can pass the second argument to account for the bookings that are canceled:

```
    // bookings = [
    //      [
    //          ...
    //          'starts_at' => '2021-01-01',
    //          'ends_at' => '2021-01-02',
    //          'cancelled_at' => '2021-04-02'
    //      ]
    // ];
    Room::first()->isBookedAt('2021-01-01', true);
    // true;
```

Advanced usage
--------------

[](#advanced-usage)

You can check if the Resource is booked or available against a period as well. When doing so, you need to make sure you are comparing period *with the same precision*. The easiest way is to simply rely on the setting of the **Coordinator** itself:

```
use BinaryCats\Coordinator\Coordinator;
use Spatie\Period\Period;

    $period = Period::make('2021-01-01 15:45:00', '2021-01-02 15:45:00', Coordinator::defaultPrecision());

    // bookings = [
    //      [
    //          ...
    //          'starts_at' => '2021-01-01 10:00:00',
    //          'ends_at' => '2021-01-02 09:00:00',
    //      ]
    // ];
    Room::first()->isBookedAt($period);
    // true;
```

By default Coordinator will look for `SECOND` as precison. You can change that by updating `coordinator.precision` config key. More about period calculations [here](https://github.com/spatie/period);

You can also check if the Resource is available for a given Model. However, since this is more of a policy concern, you need to provide closure resolution logic. For example, you may want to defer to authorization logic using a Gate:

```
use Illuminate\Support\Facades\Gate;

Room::first()->isAvailableFor(User::first(), function($model, $resource) {
    // Assuming model is \Illuminate\Contracts\Auth\Access\Authorizable
    return Gate::forUser($model)->allows('book', $resource);
});
```

or anything else:

```
Room::first()->isAvailableFor(User::first(), function($model, $resource) {
    // ... return resolution
});
```

Changelog
---------

[](#changelog)

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

Testing
-------

[](#testing)

```
composer test
```

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

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

Security
--------

[](#security)

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

Postcardware
------------

[](#postcardware)

You're free to use this package, but if it makes it to your production environment we highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using.

Credits
-------

[](#credits)

- [Cyrill Kalita](https://github.com/binary-cats)
- [All Contributors](../../contributors)

Support us
----------

[](#support-us)

Binary Cats is a webdesign agency based in Illinois, US.

License
-------

[](#license)

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

###  Health Score

35

—

LowBetter than 77% of packages

Maintenance39

Infrequent updates — may be unmaintained

Popularity15

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity61

Established project with proven stability

 Bus Factor1

Top contributor holds 71.4% 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 ~460 days

Total

4

Last Release

524d ago

Major Versions

1.0.0 → 9.0.02022-01-27

PHP version history (2 changes)1.0.0PHP ^7.3|^8.0

9.0.0PHP ^8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/ebb48367388b4368b14cca42714bb13002d7414d9dc8da19c5490ef65c059719?d=identicon)[cyrill.kalita@gmail.com](/maintainers/cyrill.kalita@gmail.com)

---

Top Contributors

[![cyrillkalita](https://avatars.githubusercontent.com/u/2401848?v=4)](https://github.com/cyrillkalita "cyrillkalita (10 commits)")[![nickfls](https://avatars.githubusercontent.com/u/12013206?v=4)](https://github.com/nickfls "nickfls (3 commits)")[![StyleCIBot](https://avatars.githubusercontent.com/u/11048387?v=4)](https://github.com/StyleCIBot "StyleCIBot (1 commits)")

---

Tags

eventlaraveleloquentschedulebinary-catsbookingappointment

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/binary-cats-coordinator/health.svg)

```
[![Health](https://phpackages.com/badges/binary-cats-coordinator/health.svg)](https://phpackages.com/packages/binary-cats-coordinator)
```

###  Alternatives

[spatie/laravel-medialibrary

Associate files with Eloquent models

6.1k43.2M632](/packages/spatie-laravel-medialibrary)[mongodb/laravel-mongodb

A MongoDB based Eloquent model and Query builder for Laravel

7.1k8.4M96](/packages/mongodb-laravel-mongodb)[defstudio/telegraph

A laravel facade to interact with Telegram Bots

816333.3k3](/packages/defstudio-telegraph)[dyrynda/laravel-model-uuid

This package allows you to easily work with UUIDs in your Laravel models.

4843.1M9](/packages/dyrynda-laravel-model-uuid)[clickbar/laravel-magellan

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

440902.9k1](/packages/clickbar-laravel-magellan)[harris21/laravel-fuse

Circuit breaker for Laravel queue jobs. Protect your workers from cascading failures.

44855.7k](/packages/harris21-laravel-fuse)

PHPackages © 2026

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