PHPackages                             yeevy/laravel-centris - 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. [API Development](/categories/api)
4. /
5. yeevy/laravel-centris

ActiveLibrary[API Development](/categories/api)

yeevy/laravel-centris
=====================

Laravel wrapper for yeevy/centris-passerelle — unofficial client for the Centris® Passerelle FTP feed (Quebec MLS). Not affiliated with or endorsed by Centris or QFREB.

v0.1.0(4d ago)00MITPHP ^8.2

Since Jul 5Compare

[ Source](https://github.com/yeevy-ai/laravel-centris)[ Packagist](https://packagist.org/packages/yeevy/laravel-centris)[ Docs](https://github.com/yeevy-ai/laravel-centris)[ RSS](/packages/yeevy-laravel-centris/feed)WikiDiscussions Synced today

READMEChangelog (1)Dependencies (13)Versions (2)Used By (0)

laravel-centris
===============

[](#laravel-centris)

[![Latest Version on Packagist](https://camo.githubusercontent.com/95e43c2a0263fa10e67297cff9ccfd0f1832d19780be3c95e04b890ba97b1cb4/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f79656576792f6c61726176656c2d63656e747269732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/yeevy/laravel-centris)[![Tests](https://camo.githubusercontent.com/7e611cb91a075a95d6bc937ce9b20804ac7f50407addff00cb4a68ca405a09c7/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f79656576792d61692f6c61726176656c2d63656e747269732f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/yeevy-ai/laravel-centris/actions/workflows/run-tests.yml)[![Total Downloads](https://camo.githubusercontent.com/f6c29707603441f6f83cf6b0ae54bbfb798217253eeaba8ea0042c6c3887abdc/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f79656576792f6c61726176656c2d63656e747269732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/yeevy/laravel-centris)

> **Non officiel. Aucune affiliation avec Centris ou l'APCIQ/QFREB, ni endossement de leur part. Requiert une entente de diffusion valide.**
>
> **Unofficial. Not affiliated with or endorsed by Centris or QFREB. Requires a valid diffusion agreement.**

[Français](#fran%C3%A7ais) | [English](#english)

---

Français
--------

[](#français)

Enveloppe Laravel pour [`yeevy/centris-passerelle`](https://github.com/yeevy-ai/centris-passerelle), le client PHP non officiel du flux FTP **Centris® Passerelle** (inscriptions MLS du Québec). Fournit la configuration, l'injection de dépendances et — à venir — la commande de synchronisation, les jobs en file d'attente et les événements.

### Installation

[](#installation)

```
composer require yeevy/laravel-centris

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

### Utilisation

[](#utilisation)

Les 14 analyseurs et le validateur de dérive sont des singletons du conteneur, prêts à injecter :

```
use Yeevy\CentrisPasserelle\Parser\ListingsParser;
use Yeevy\CentrisPasserelle\Validation\SnapshotValidator;

class SyncListings
{
    public function __construct(
        private ListingsParser $parser,
        private SnapshotValidator $validator,
    ) {}

    public function handle(): void
    {
        $file = config('centris.feed_path').'/INSCRIPTIONS.TXT';

        $this->validator->validateFile($file); // lève ColumnMapMismatch si la structure a dérivé

        foreach ($this->parser->parseFile($file) as $listing) {
            // $listing->mlsNumber, $listing->status, $listing->dirtyHash…
        }
    }
}
```

### Synchronisation

[](#synchronisation)

Implémentez `ListingRepository` contre votre stockage et liez-la dans un fournisseur de services :

```
$this->app->singleton(
    \Yeevy\CentrisPasserelle\Contracts\ListingRepository::class,
    EloquentListingRepository::class,
);
```

Puis lancez la synchronisation (validation de dérive, upsert avec saut des lignes inchangées, réconciliation des retraits) :

```
php artisan centris:sync                 # utilise centris.feed_path
php artisan centris:sync --path=/depot   # dossier ou fichier explicite
```

Les événements du noyau traversent le système d'événements Laravel — écoutez-les comme d'habitude :

```
Event::listen(function (\Yeevy\CentrisPasserelle\Events\ListingRemoved $event) {
    // dépublier $event->mlsNumber
});
```

Planifiez-la comme n'importe quelle commande : `Schedule::command('centris:sync')->twiceDaily(6, 18);`

### Récupération FTP

[](#récupération-ftp)

Sans `--path`, `centris:sync` utilise la source configurée. Réglez `CENTRIS_SOURCE=ftp` et la commande télécharge d'abord le dépôt Passerelle dans `feed_path` :

```
CENTRIS_SOURCE=ftp
CENTRIS_FTP_HOST=ftp.example.test
CENTRIS_FTP_USERNAME=votre-code
CENTRIS_FTP_PASSWORD=********
CENTRIS_EXTRACT_ARCHIVES=true   # si votre entente livre un ZIP
```

Pour SFTP ou une source sur mesure, reliez à nouveau le contrat `FeedSource` dans votre fournisseur de services.

### Photos en file d'attente

[](#photos-en-file-dattente)

`centris:photos` met en file un job par photo de `PHOTOS.TXT` ; chaque job télécharge dans des fichiers adressés par contenu (`{sha256}.jpg` — les octets identiques ne sont stockés qu'une fois) puis déclenche `PhotoDownloaded` :

```
php artisan centris:photos
```

```
Event::listen(function (\Yeevy\LaravelCentris\Events\PhotoDownloaded $event) {
    // associer $event->photo->path à l'inscription $event->photo->photo->mlsNumber
});
```

### Configuration

[](#configuration)

`config/centris.php` :

- `feed_path` — répertoire des fichiers d'instantané (`CENTRIS_FEED_PATH`)
- `source` / `ftp` / `extract_archives` — provenance de l'instantané pour `centris:sync`
- `photos` — répertoire des photos (`CENTRIS_PHOTOS_PATH`) et file d'attente (`CENTRIS_PHOTOS_QUEUE`)
- `column_profiles` — profil de carte nommé par type de fichier
- `column_overrides` — surcharges de positions propres à votre entente, p. ex. `'listings' => ['status_code' => 118]`
- `validation` — seuils de la détection de dérive

### Licence

[](#licence)

[MIT](LICENSE.md) — © Digital Unity Inc. ([Yeevy](https://yeevy.ai))

---

English
-------

[](#english)

Laravel wrapper for [`yeevy/centris-passerelle`](https://github.com/yeevy-ai/centris-passerelle), the unofficial PHP client for the **Centris® Passerelle** FTP feed (Quebec MLS listings). Provides configuration, dependency injection, and — upcoming — the sync command, queued jobs, and events.

### Installation

[](#installation-1)

```
composer require yeevy/laravel-centris

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

### Usage

[](#usage)

All 14 parsers and the drift validator are container singletons, ready to inject:

```
use Yeevy\CentrisPasserelle\Parser\ListingsParser;
use Yeevy\CentrisPasserelle\Validation\SnapshotValidator;

class SyncListings
{
    public function __construct(
        private ListingsParser $parser,
        private SnapshotValidator $validator,
    ) {}

    public function handle(): void
    {
        $file = config('centris.feed_path').'/INSCRIPTIONS.TXT';

        $this->validator->validateFile($file); // throws ColumnMapMismatch on structure drift

        foreach ($this->parser->parseFile($file) as $listing) {
            // $listing->mlsNumber, $listing->status, $listing->dirtyHash…
        }
    }
}
```

### Synchronization

[](#synchronization)

Implement `ListingRepository` against your storage and bind it in a service provider:

```
$this->app->singleton(
    \Yeevy\CentrisPasserelle\Contracts\ListingRepository::class,
    EloquentListingRepository::class,
);
```

Then run the sync (drift validation, dirty-hash upserts, removal reconciliation):

```
php artisan centris:sync                 # uses centris.feed_path
php artisan centris:sync --path=/drop    # explicit directory or file
```

The core events flow through Laravel's event system — listen as usual:

```
Event::listen(function (\Yeevy\CentrisPasserelle\Events\ListingRemoved $event) {
    // unpublish $event->mlsNumber
});
```

Schedule it like any command: `Schedule::command('centris:sync')->twiceDaily(6, 18);`

### FTP fetch

[](#ftp-fetch)

Without `--path`, `centris:sync` uses the configured source. Set `CENTRIS_SOURCE=ftp` and the command downloads the Passerelle drop into `feed_path` first:

```
CENTRIS_SOURCE=ftp
CENTRIS_FTP_HOST=ftp.example.test
CENTRIS_FTP_USERNAME=your-code
CENTRIS_FTP_PASSWORD=********
CENTRIS_EXTRACT_ARCHIVES=true   # if your agreement delivers a ZIP
```

For SFTP or a custom source, rebind the `FeedSource` contract in your service provider.

### Queued photos

[](#queued-photos)

`centris:photos` queues one job per `PHOTOS.TXT` row; each job downloads into content-addressed files (`{sha256}.jpg` — identical bytes are stored once) and fires `PhotoDownloaded`:

```
php artisan centris:photos
```

```
Event::listen(function (\Yeevy\LaravelCentris\Events\PhotoDownloaded $event) {
    // associate $event->photo->path with listing $event->photo->photo->mlsNumber
});
```

### Configuration

[](#configuration-1)

`config/centris.php`:

- `feed_path` — snapshot files directory (`CENTRIS_FEED_PATH`)
- `source` / `ftp` / `extract_archives` — where `centris:sync` gets the snapshot
- `photos` — photo directory (`CENTRIS_PHOTOS_PATH`) and queue (`CENTRIS_PHOTOS_QUEUE`)
- `column_profiles` — named map profile per file type
- `column_overrides` — per-agreement position overrides, e.g. `'listings' => ['status_code' => 118]`
- `validation` — drift-detection thresholds

### License

[](#license)

[MIT](LICENSE.md) — © Digital Unity Inc. ([Yeevy](https://yeevy.ai))

###  Health Score

36

—

LowBetter than 79% of packages

Maintenance99

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity35

Early-stage or recently created project

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

Unknown

Total

1

Last Release

4d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/1685702?v=4)[Chris Harrison](/maintainers/digitalunity)[@digitalunity](https://github.com/digitalunity)

---

Tags

laravelmlsreal-estateimmobilierquebecyeevycentrispasserelle

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/yeevy-laravel-centris/health.svg)

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

###  Alternatives

[dedoc/scramble

Automatic generation of API documentation for Laravel applications.

2.1k11.2M103](/packages/dedoc-scramble)[simplestats-io/laravel-client

Server-side analytics for Laravel that follows the full funnel from visit to registration to payment, attributed to the channel that drove it. Revenue, MRR, churn and ad-spend profit (ROAS/CAC) per channel. GDPR compliant, ad-blocker proof.

5022.3k](/packages/simplestats-io-laravel-client)[defstudio/telegraph

A laravel facade to interact with Telegram Bots

813335.6k3](/packages/defstudio-telegraph)[shopware/core

Shopware platform is the core for all Shopware ecommerce products.

585.6M582](/packages/shopware-core)[codebar-ag/laravel-docuware

DocuWare integration with Laravel

1123.7k](/packages/codebar-ag-laravel-docuware)[rawilk/profile-filament-plugin

Profile &amp; MFA starter kit for filament.

3914.8k](/packages/rawilk-profile-filament-plugin)

PHPackages © 2026

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