innobrain / laravel-onoffice-adapter
Laravel package to joyfully interact with the onOffice API
Package info
github.com/innobraingmbh/laravel-onoffice-adapter
pkg:composer/innobrain/laravel-onoffice-adapter
Fund package maintenance!
Requires
- php: ^8.2
- illuminate/contracts: ^11.0|^12.0|^13.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- driftingly/rector-laravel: ^2.0
- guzzlehttp/guzzle: ^7.8
- larastan/larastan: ^3.0
- laravel/pint: ^1.14
- nunomaduro/collision: ^7.10|^8.1|^9.0
- orchestra/testbench: ^9.0|^10.0|^11.0
- pestphp/pest: ^3.0|^4.0
- pestphp/pest-plugin-arch: ^3.0|^4.0
- pestphp/pest-plugin-laravel: ^3.0|^4.0
- phpstan/extension-installer: ^1.3
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
- rector/rector: ^2.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-main
- v2.1.0
- v2.0.0
- v1.25.0
- v1.24.0
- v1.23.0
- v1.22.0
- v1.21.0
- v1.20.1
- v1.20.0
- v1.19.0
- v1.18.0
- v1.17.1
- v1.17.0
- v1.16.1
- v1.16.0
- v1.15.1
- v1.15.0
- v1.14.0
- v1.13.1
- v1.13.0
- v1.12.0
- v1.11.2
- v1.11.1
- v1.11.0
- v1.10.0
- v1.9.4
- v1.9.3
- v1.9.2
- v1.9.1
- v1.9.0
- v1.8.2
- v1.8.1
- v1.8.0
- v1.7.2
- v1.7.1
- v1.7.0
- v1.6.0
- v1.5.10
- v1.5.9
- v1.5.8
- v1.5.7
- v1.5.6
- v1.5.5
- v1.5.4
- v1.5.3
- v1.5.2
- v1.5.1
- v1.5.0
- v1.4.5
- v1.4.4
- v1.4.3
- v1.4.2
- v1.4.1
- v1.4.0
- v1.3.0
- v1.2.7
- v1.2.6
- v1.2.5
- v1.2.4
- v1.2.3
- v1.2.2
- v1.2.1
- v1.2.0
- v1.1.3
- v1.1.2
- v1.1.1
- v1.1.0
- v1.0.0
- v0.13.6
- v0.13.5
- v0.13.4
- v0.13.3
- v0.13.2
- v0.13.1
- v0.13.0
- v0.12.4
- v0.12.3
- v0.12.2
- v0.12.1
- v0.12.0
- v0.11.0
- v0.10.3
- v0.10.2
- v0.10.1
- v0.10.0
- v0.9.1
- v0.9.0
- v0.8.6
- v0.8.5
- v0.8.4
- v0.8.3
- v0.8.2
- v0.8.1
- v0.8.0
- v0.7.7
- v0.7.6
- v0.7.5
- v0.7.4
- v0.7.3
- v0.7.2
- v0.7.1
- v0.7.0
- v0.6.0
- v0.5.4
- v0.5.3
- v0.5.2
- v0.5.1
- v0.5.0
- v0.4.1
- v0.4.0
- v0.3.0
- v0.2.3
- v0.2.2
- v0.2.1
- v0.2.0
- v0.1.0
- dev-feat/read-only-mode
- dev-reuse-http-connection
- dev-claude/confident-archimedes-ozqovw
- dev-release/v2.0.0
- dev-hotfix/search-criteria
- dev-claude/confident-archimedes-na4til
- dev-claude/confident-archimedes-a5seca
- dev-claude/confident-archimedes-e1cvvi
- dev-fix/sortorder-parameters
- dev-fix/appointments-pagination-doesnt-exist
- dev-claude/confident-archimedes-5g7oqv
- dev-claude/confident-archimedes-d2ltdw
- dev-fix/task-listoffset
- dev-task-module
- dev-add-task-repository
- dev-docs
- dev-after
- dev-concurrency
This package is auto-updated.
Last update: 2026-09-14 10:25:07 UTC
README
A query builder for the onOffice API with an Eloquent-style interface.
Features
- Query builder -
select(),where(),orderBy(),limit(),offset() - Repositories - Estates, addresses, activities, appointments, tasks, search criteria, files, relations, and more
- Pagination -
get()reads every page;each()processes one page at a time - Middlewares - Run code before and after each request
- Testing - Fake responses and record factories
- Files - Upload, chunk, and link files to records
Installation
composer require innobrain/laravel-onoffice-adapter
Add your onOffice API credentials to .env:
ON_OFFICE_TOKEN=your-token
ON_OFFICE_SECRET=your-secret
To change retry settings or headers, publish the config file:
php artisan vendor:publish --tag="onoffice-adapter-config"
The package keeps one HTTP connection to the onOffice API open per PHP process and reuses it for every request, which skips the TCP and TLS handshake on all but the first call. Long-lived processes such as queue workers and Octane benefit most. If a stale connection is closed by the server, the request fails with a connection error and the retry settings above take over. Set reuse_connection to false in the config to open a fresh connection per request instead.
Usage
Basic Queries
use Innobrain\OnOfficeAdapter\Facades\EstateRepository; // Get all estates $estates = EstateRepository::query()->get(); // Find by ID $estate = EstateRepository::query()->find(123); // Get first result $estate = EstateRepository::query()->first(); // Count results $count = EstateRepository::query()->count();
Building Queries
Chain methods to filter, sort, and limit results:
$estates = EstateRepository::query() ->select(['Id', 'kaufpreis', 'lage']) ->where('status', 1) ->where('kaufpreis', '<', 500000) ->orderByDesc('kaufpreis') ->limit(10) ->get();
Available Methods
| Method | Description |
|---|---|
select($fields) |
Fields to retrieve |
where($field, $op, $value) |
Filter by condition |
whereIn($field, $values) |
Filter by array of values |
whereLike($field, $pattern) |
Pattern matching |
whereBetween($field, $min, $max) |
Range filter |
orderBy($field) |
Sort ascending |
orderByDesc($field) |
Sort descending |
limit($n) |
Max results |
offset($n) |
Skip results |
Large Datasets
each() processes one page per callback:
EstateRepository::query() ->each(function (array $estates) { foreach ($estates as $estate) { // Process chunk } });
A failed page throws OnOfficeException. No partial results. Chunks already passed to the callback are not rolled back.
Available Repositories
| Repository | Description |
|---|---|
EstateRepository |
Real estate properties |
AddressRepository |
Contacts and addresses |
ActivityRepository |
Activity logs |
ActionRepository |
Action kind types |
AppointmentRepository |
Calendar appointments |
TaskRepository |
Tasks |
UserRepository |
onOffice users |
SearchCriteriaRepository |
Buyer search profiles |
FieldRepository |
Field metadata |
FileRepository |
File uploads and downloads |
FilterRepository |
Saved filters |
RelationRepository |
Record relationships |
SettingRepository |
System settings |
MarketplaceRepository |
Marketplace integration |
LinkRepository |
URL links |
LogRepository |
Log entries |
MacroRepository |
Macros |
LastSeenRepository |
Recently viewed records |
File Uploads
$tmpUploadId = FileRepository::upload() ->save(base64_encode($fileContent)); FileRepository::upload()->link($tmpUploadId, [ 'module' => 'estate', 'relatedRecordId' => '12345', ]); // Or upload in blocks and link in one call FileRepository::upload() ->uploadInBlocks() ->saveAndLink(base64_encode($fileContent), [ 'module' => 'estate', 'relatedRecordId' => '12345', ]);
Creating Activities
ActivityRepository::query() ->addressIds($recordIds) ->estateId($estateId) ->create([ 'datetime' => $event->getDateFormatted(), 'actionkind' => 'Newsletter', 'actiontype' => 'Hard Bounce', 'note' => $message, ]);
Middlewares
Run code before each request:
use Innobrain\OnOfficeAdapter\Facades\BaseRepository; use Innobrain\OnOfficeAdapter\Dtos\OnOfficeRequest; BaseRepository::query() ->before(function (OnOfficeRequest $request) { Log::info('Sending request', ['request' => $request->toArray()]); }) ->call(new OnOfficeRequest(/* ... */));
Debugging
// Dump and die BaseRepository::query()->dd()->call(/* ... */); // Dump without stopping BaseRepository::query()->dump()->call(/* ... */); // Record requests and responses BaseRepository::record(); BaseRepository::query()->call(/* ... */); $lastPair = BaseRepository::lastRecorded(); // [OnOfficeRequest, array]
Helpers
Default field lists and empty-value cleanup:
use Innobrain\OnOfficeAdapter\Services\OnOfficeService; $estates = EstateRepository::query() ->select(OnOfficeService::DEFAULT_ESTATE_INFO_FIELDS) ->get(); // Remove fields with empty values ("", "0.00", [], null) $estates = $estates->map(fn (array $estate) => clear_elements($estate));
Testing
Fake responses in tests:
use Innobrain\OnOfficeAdapter\Facades\EstateRepository; use Innobrain\OnOfficeAdapter\Facades\Testing\RecordFactories\EstateFactory; EstateRepository::fake(EstateRepository::response([ EstateRepository::page(recordFactories: [ EstateFactory::make()->id(1)->set('kaufpreis', 250000), EstateFactory::make()->id(2)->set('kaufpreis', 300000), ]), ])); $estates = EstateRepository::query()->get(); expect($estates)->toHaveCount(2); EstateRepository::assertSentCount(1);
Prevent Unstubbed Requests
EstateRepository::preventStrayRequests(); EstateRepository::fake(/* ... */); // Any unstubbed request will throw StrayRequestException
Multiple Pages
EstateRepository::fake(EstateRepository::response([ EstateRepository::page(recordFactories: [ EstateFactory::make()->id(1), ]), EstateRepository::page(recordFactories: [ EstateFactory::make()->id(2), ]), ])); $estates = EstateRepository::query()->get(); expect($estates)->toHaveCount(2);
Sequences (Multiple Calls)
EstateRepository::fake([ EstateRepository::response([/* first call */]), EstateRepository::response([/* second call */]), ]); // Or repeat the same response EstateRepository::fake(EstateRepository::sequence( EstateRepository::response([/* ... */]), times: 30, ));
See Testing for factories and assertions.
Development
composer test # Run tests composer analyse # Static analysis (PHPStan) composer format # Code formatting (Laravel Pint)
Changelog
See CHANGELOG. For breaking changes, see UPGRADE.
Security Vulnerabilities
See the security policy.
Credits
License
MIT. See LICENSE.