PHPackages                             apptank/horusync - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. apptank/horusync

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

apptank/horusync
================

Data synchronization between mobile devices and a Laravel application

v0.17.4(2mo ago)0802AGPL-3.0-onlyPHPPHP ^8.3

Since Sep 17Pushed 2mo agoCompare

[ Source](https://github.com/apptanksas/horus-sync-php)[ Packagist](https://packagist.org/packages/apptank/horusync)[ RSS](/packages/apptank-horusync/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (16)Versions (105)Used By (0)

[![Horusync Logo](https://raw.githubusercontent.com/apptanksas/horus-sync-php/master/assets/logo-horusync.svg)](https://raw.githubusercontent.com/apptanksas/horus-sync-php/master/assets/logo-horusync.svg)
[![Build Status](https://github.com/apptanksas/horus-sync-php/actions/workflows/unit_tests.yml/badge.svg)](https://github.com/apptanksas/horus-sync-php/actions/workflows/unit_tests.yml/badge.svg)[![Latest Stable Version](https://camo.githubusercontent.com/fc70faac83082e89d1caeeda295ab507a293af81049c8b7b1632cc00503161af/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f61707074616e6b2f686f727573796e63)](https://camo.githubusercontent.com/fc70faac83082e89d1caeeda295ab507a293af81049c8b7b1632cc00503161af/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f61707074616e6b2f686f727573796e63)[![License](https://camo.githubusercontent.com/006a45db2cfac748b108ae9da9f5755a992920124a3fdecb0f4a7b8df7389993/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f61707074616e6b7361732f686f7275732d73796e632d706870)](https://camo.githubusercontent.com/006a45db2cfac748b108ae9da9f5755a992920124a3fdecb0f4a7b8df7389993/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f61707074616e6b7361732f686f7275732d73796e632d706870)[![Ask DeepWiki](https://camo.githubusercontent.com/0f5ae213ac378635adeb5d7f13cef055ad2f7d9a47b36de7b1c67dbe09f609ca/68747470733a2f2f6465657077696b692e636f6d2f62616467652e737667)](https://deepwiki.com/apptanksas/horus-sync-php)

**Please note:** This library currently is in testing stage until publish the version 1.0.0.

Horus Sync
==========

[](#horus-sync)

This library provides an easy way to manage data synchronization between a remote database on a server and a local database on a mobile device. It defines a set of synchronizable entities by specifying their parameters and relationships with other entities.

### Features

[](#features)

- **Data Synchronization:** Enables synchronization of the defined entities' data between the local database and the remote database.
- **Schema Migration:** Allows retrieval of the schema for synchronizable entities and their relationships.
- **Integrity Validation:** Ensures the integrity of synchronized data.
- **Authentication and Permissions:** Defines an authenticated user and the permissions associated with the entities.
- **Upload Files:** Allows uploading files to the server.
- **Middlewares:** Supports defining custom middlewares for synchronization routes.
- **UUID Support:** Allows specifying whether UUIDs or Int will be used as the primary key for entities.
- **Foreign Key Support:** Supports defining foreign keys in synchronizable entities with cascading delete functionality.
- **UserActingAs Support:** Indicates if a user has permission to act as another user and access the entities where permissions have been granted.
- **Support for Synchronizable Entity Types:** Supports defining entities as writable or readable, depending on whether they can be edited or not.

📦 Installation
--------------

[](#-installation)

This library must be used with Laravel version 11 or higher.

Use the following command to install the package using Composer:

```
composer require apptank/horusync
```

🔨 Usage
-------

[](#-usage)

All synchronizable models with editable records must inherit from `WritableEntitySynchronizable`, defining the properties they contain. If you want a read-only entity, you should inherit from `ReadableEntitySynchronizable`.

You can use an artisan command to generate a synchronizable model for you. You just need to specify the path where the model should be stored. The following example will create a model in `App/Models/Sync/MyModelSync`:

```
php artisan horus:entity MyModelSync
```

```
namespace App\Models\Sync;

use AppTank\Horus\Core\Entity\SyncParameter;
use AppTank\Horus\Illuminate\Database\WritableEntitySynchronizable;

class MyModel extends WritableEntitySynchronizable
{
    public static function parameters(): array
    {
        return [
            // Define the parameters of the entity
            SyncParameter::createString("name", 1),
            SyncParameter::createInt("age", 1),
            SyncParameter::createPrimaryKeyString("email", 1),
            SyncParameter::createTimestamp("datetime", 1),
            SyncParameter::createBoolean("active", 1),
            SyncParameter::createFloat("price", 1),
            SyncParameter::createRelationOneToMany("children", [ChildModel::class], 1)
        ];
    }

    public static function getEntityName(): string
    {
        return "my_model";
    }

    public static function getVersionNumber(): int
    {
        return 1;
    }
}
```

If you want to create a read-only entity, you can add the `--readable` option to the artisan command.

```
php artisan horus:entity MyModelSync --readable
```

🚀 Quick Start
-------------

[](#-quick-start)

### 1. Initialization

[](#1-initialization)

It is necessary to initialize the Horus container in the `AppServiceProvider` of Laravel by passing an array with the hierarchical map of entities.

You can optionally

- Define the database connection name
- Whether UUIDs or Int will be used as the primary key.
- Define a prefix for the tables of entities in the database.
- Enable or disable the validation of access to entities. Improve performance by disabling this option.
- Prefix for the tables of entities in the database.
- Define the entity restrictions.

```
class AppServiceProvider extends ServiceProvider
{

    public function boot(): void
    {
       // Define the hierarchical map of entities
       $entityMap = [
            MyModel::class => [
                ChildModel::class
            ]
       ];

       // Define the configuration
       $config = new Config(
            validateAccess: true,
            connectionName: "sync_database",
            usesUUIDs: true,
            prefixTables: 'hs',
            entityRestrictions: [
                new MaxCountEntityRestriction("user_id","entity_name", maxCount: 10)
            ],
        );

         // Initialize Horus
        Horus::initialize($entityMap)->setConfig($config);
    }

}
```

### 2. Run Migrations

[](#2-run-migrations)

Once the Horus container has been initialized, you need to run the synchronization tables migrations.

```
php artisan migrate
```

⬆️ Enable upload files
----------------------

[](#️-enable-upload-files)

To enable the upload files feature, you need setup a file handler in horus initialization, implementing the `IFileHandler` interface.

```
Horus::setFileHandler($this->app->make(IFileHandler::class));
```

In your writable entity synchronizable model, you can define the file attribute using the `SyncParameter::createReferenceFile` method.

```
class UserImageModel extends WritableEntitySynchronizable
{
    public static function parameters(): array
    {
        return [
            // User Id
            SyncParameter::createUUIDForeignKey("user_id", 1,"users"),
            // Reference to the image file
            SyncParameter::createReferenceFile("image", 1),
        ];
    }
}
```

### Local File Handler example

[](#local-file-handler-example)

The following example shows how to implement a file handler for local file storage using Laravel's storage system.

```
class LocalFileHandler implements IFileHandler
{
    /**
     * @throws \Exception
     */
    function upload(int|string $userOwnerId, string $fileId, string $path, UploadedFile $file): FileUploaded
    {
        $filename = basename($path);
        $basePath = dirname($path);

        $pathResult = $file->storeAs($basePath, $filename);

        if (!$pathResult) {
            throw new \Exception("Error uploading file");
        }

        $mimeType = $file->getMimeType();
        $publicUrl = $this->generateUrl($pathResult);

        return new FileUploaded(
            $fileId,
            $mimeType,
            $pathResult,
            $publicUrl,
            $userOwnerId
        );
    }

    function delete(string $pathFile): bool
    {
        return Storage::delete($pathFile);
    }

    function getMimeTypesAllowed(): array
    {
        return MimeType::IMAGES;
    }

    function copy(string $pathFrom, string $pathTo): bool
    {
        return Storage::copy($pathFrom, $pathTo);
    }

    function generateUrl(string $path): string
    {
        return Storage::url($path);
    }
}
```

### Prune files

[](#prune-files)

If you want to delete files that are no longer referenced by any entity, you can use the following command:

```
php artisan horus:prune --expirationDays=7
```

- **expirationDays:** The number of days after which files will be deleted.

↔️ Middlewares
--------------

[](#️-middlewares)

If you want to implement custom middlewares for the synchronization routes, you can do so in your Service Provider as follows:

```
Horus::setMiddleware([MyMiddleware::class,'throttle:60,1']);
```

🔒 Authentication and Permissions
--------------------------------

[](#-authentication-and-permissions)

The following code shows how to configure user authentication and the permissions associated with entities. Using the UserAuth class, you define an authenticated user along with the entities they have access to and the corresponding permissions.

```
Horus::getInstance()->setUserAuthenticated(
 new UserAuth(
   "07a35af0-7317-41e4-99a3-e3583099aff2", // User Id Authenticated
   [ // Array of Entities Granted
   new EntityGranted(
   "971785f7-0f01-46cd-a3ce-af9ce6273d3d", // User Owner Id
   "entity_name", // Entity Name
    "9135e859-b053-4cfb-b701-d5f240b0aab1", // Entity Id
    // Set the permissions for the entity
   , new AccessLevel(Permission::READ, Permission::CREATE)),
    // User Acting As
   new UserAuth("b253a0e8-027b-463c-b87a-b18f09c99ddd")
   ]
 )
);
```

#### (Recommend) Setup entity granted on validate entity was granted to void sync issues.

[](#recommend-setup-entity-granted-on-validate-entity-was-granted-to-void-sync-issues)

```
$config = new Config(true);
$config->setupOnValidateEntityWasGranted(function () {
    return [
        new EntityGranted($userOwnerId,
        new EntityReference($entityName, $entityId), AccessLevel::all())
    ];
});
Horus::getInstance()->setConfig($config);
```

### ⛔ Entity Restrictions

[](#-entity-restrictions)

If you want to apply a restriction to an entity, you can use the next restriction classes:

- **MaxCountEntityRestriction**: Restricts the number of records that can be synchronized for an entity to specific user.
- **FilterEntityRestriction**: This restriction allows you to filter the records from an entity can be obtained given a set of parameters. This is useful when you want to limit the data that can be downloaded to client based on certain criteria.
- **LimitCountEntityParentRetrieveRestriction**: This restriction allows you to limit the number of parent records that can be retrieved by user owner for a specific entity.
- **LimitCountEntityChildrenRetrieveRestriction**: This restriction allows you to limit the number of children records that can be retrieved from a parent entity by user owner for a specific entity.

#### Setup after initialization

[](#setup-after-initialization)

By default, the setup is set the Config class in the Horus initialization, but if you want to change the restrictions after you can use the next code:

```
Horus::getInstance()->setEntityRestrictions([
    new MaxCountEntityRestriction("user_id","entity_name", maxCount: 10),
    new FilterEntityRestriction("entity_name", [
       new ParameterFilter("country", "CO")
    ])
]);
```

### 🍒 Shared entities

[](#-shared-entities)

If you want to share records from specific entities, you can use the method `setSharedEntities` or `setupOnSharedEntities` in the Horus instance like this:

```
Horus::getInstance()->setSharedEntities([
    new EntityReference("entity_name", "entity_id")
]);
```

(Recommend) This way, only setup the shared entities when Horus needs it.

```
Horus::getInstance()->setupOnSharedEntities(function(){
    return [new EntityReference("entity_name", "entity_id")];
});
```

### ✉️ Events

[](#️-events)

If you want to listen to events that occur during synchronization, you can use the following code:

#### Insert Event

[](#insert-event)

```
Event::listen("horus.sync.insert", function (string $entityName, array $data) {
    // Your code here
});
```

#### Update Event

[](#update-event)

```
Event::listen("horus.sync.update", function (string $entityName, array $data) {
    // Your code here
});
```

#### Delete Event

[](#delete-event)

```
Event::listen("horus.sync.delete", function (string $entityName, array $data) {
    // Your code here
});
```

###  Health Score

46

—

FairBetter than 93% of packages

Maintenance85

Actively maintained with recent releases

Popularity16

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity61

Established project with proven stability

 Bus Factor1

Top contributor holds 51.1% 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 ~5 days

Total

97

Last Release

76d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/5c0855ea7f5adcba360aed87a15080d3c4798890fa33bb2316331a29edc3fc1c?d=identicon)[jospina\_apptank](/maintainers/jospina_apptank)

---

Top Contributors

[![jhospina](https://avatars.githubusercontent.com/u/6635045?v=4)](https://github.com/jhospina "jhospina (96 commits)")[![jospina-apptank](https://avatars.githubusercontent.com/u/114356143?v=4)](https://github.com/jospina-apptank "jospina-apptank (90 commits)")[![HarrisonOspina](https://avatars.githubusercontent.com/u/108702254?v=4)](https://github.com/HarrisonOspina "HarrisonOspina (2 commits)")

---

Tags

laravelmobilesyncdata-sync

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/apptank-horusync/health.svg)

```
[![Health](https://phpackages.com/badges/apptank-horusync/health.svg)](https://phpackages.com/packages/apptank-horusync)
```

###  Alternatives

[barryvdh/laravel-ide-helper

Laravel IDE Helper, generates correct PHPDocs for all Facade classes, to improve auto-completion.

14.9k123.0M687](/packages/barryvdh-laravel-ide-helper)[yajra/laravel-datatables-oracle

jQuery DataTables API for Laravel

4.9k33.8M339](/packages/yajra-laravel-datatables-oracle)[spatie/laravel-enum

Laravel Enum support

3655.4M31](/packages/spatie-laravel-enum)[yajra/laravel-datatables-editor

Laravel DataTables Editor plugin for Laravel 5.5+.

1186.1M2](/packages/yajra-laravel-datatables-editor)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

245.2k](/packages/aedart-athenaeum)[laragear/preload

Effortlessly make a Preload script for your Laravel application.

119363.5k](/packages/laragear-preload)

PHPackages © 2026

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