sergeybruhin / laravel-nano-crm
Laravel integration package for nano-crm-api
Requires
- php: ^8.3
- illuminate/console: ^11.0|^12.0|^13.0
- illuminate/queue: ^11.0|^12.0|^13.0
- illuminate/support: ^11.0|^12.0|^13.0
- sergeybruhin/nano-crm-client: ^0.0.1
Requires (Dev)
- orchestra/testbench: ^9.0|^10.0
This package is auto-updated.
Last update: 2026-05-26 22:49:58 UTC
README
Laravel integration package for nano-crm-api — wraps nano-crm-client with a service container singleton, a facade, and queue jobs for asynchronous lead and contact submission to a self-hosted Nano CRM API.
Requirements
- PHP 8.3+
- Laravel 11, 12, or 13
Installation
composer require sergeybruhin/laravel-nano-crm
The service provider and NanoCrm facade alias are registered automatically via package discovery.
Configuration
Publish the config file:
php artisan vendor:publish --tag=nano-crm-config
This creates config/nano-crm.php. Set the following environment variables:
| Variable | Default | Description |
|---|---|---|
NANO_CRM_BASE_URL |
http://nano-crm-api |
Base URL of the nano-crm-api service |
NANO_CRM_SERVICE_TOKEN |
— | M2M Bearer token (required) |
NANO_CRM_TIMEOUT |
10 |
HTTP request timeout in seconds |
NANO_CRM_QUEUE |
default |
Queue used by the async jobs |
On a Docker internal network the base URL is typically the container hostname, e.g. http://nano-crm-api.
Usage
Facade
use NanoCrm\Laravel\Facades\NanoCrm; use NanoCrm\Client\Dto\CreateLeadInput; $lead = NanoCrm::leads()->create(new CreateLeadInput( contact: ['full_name' => 'Ivan Petrov', 'phone' => '+79001234567'], source: 'example.com', type: 'callback', ));
Dependency injection
use NanoCrm\Laravel\NanoCrmManager; use NanoCrm\Client\Dto\CreateContactInput; class MyService { public function __construct(private NanoCrmManager $crm) {} public function sync(): void { $contact = $this->crm->contacts()->create(new CreateContactInput( fullName: 'Ivan Petrov', primaryPhoneNumber: '+79001234567', )); } }
Queue jobs
Dispatch jobs to submit leads or contacts asynchronously. They use the queue configured in NANO_CRM_QUEUE and retry up to 3 times with a 10 s backoff.
use NanoCrm\Laravel\Jobs\SendLeadToNanoCrm; use NanoCrm\Laravel\Jobs\SendContactToNanoCrm; use NanoCrm\Client\Dto\CreateLeadInput; use NanoCrm\Client\Dto\CreateContactInput; // Dispatch a lead (fire and forget) SendLeadToNanoCrm::dispatch(new CreateLeadInput( contact: ['full_name' => 'Ivan Petrov', 'phone' => '+79001234567'], source: 'example.com', type: 'callback', )); // Dispatch with a success callback SendLeadToNanoCrm::dispatch( new CreateLeadInput(...), onSuccessCallback: fn (LeadDto $lead) => Cache::put("lead:{$lead->uuid}", $lead), ); // Dispatch a contact SendContactToNanoCrm::dispatch(new CreateContactInput( fullName: 'Ivan Petrov', primaryPhoneNumber: '+79001234567', ));
Both jobs are tagged ['nano-crm', 'lead'] / ['nano-crm', 'contact'] for Horizon visibility.
Artisan command
php artisan nano-crm:ping
Checks that the service is reachable and the token is valid. A 404 response from the API counts as success (the service is up and authenticated). Useful for container readiness checks.
Testing
Swap the underlying HTTP client in tests using setClient():
use GuzzleHttp\Client; use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\HandlerStack; use GuzzleHttp\Psr7\Response; use NanoCrm\Client\NanoCrmClient; use NanoCrm\Laravel\NanoCrmManager; $mock = new MockHandler([ new Response(201, [], json_encode([ 'uuid' => '019602a0-0000-7000-8000-000000000001', 'type' => 'callback', 'source' => 'example.com', 'is_test' => false, 'sent_at' => '2024-01-01T00:00:00+00:00', 'created_at' => '2024-01-01T00:00:00+00:00', 'updated_at' => '2024-01-01T00:00:00+00:00', 'contact' => null, 'utm' => null, 'remote_ids' => null, 'form' => null, 'meta' => null, 'form_key' => null, ])), ]); $http = new Client(['handler' => HandlerStack::create($mock)]); $client = new NanoCrmClient($http); $manager = app(NanoCrmManager::class); $manager->setClient($client); $lead = $manager->leads()->create(...);
License
MIT