Installation
composer require ang3/odoo-bundle
Configure .env
ODOO_API_URL=https://your-odoo-instance.com
ODOO_API_DATABASE=your_database
ODOO_API_USERNAME=admin
ODOO_API_PASSWORD=your_password
Configure config/packages/ang3_odoo.yaml
ang3_odoo:
default_connection: default
connections:
default:
url: '%env(resolve:ODOO_API_URL)%'
database: '%env(resolve:ODOO_API_DATABASE)%'
user: '%env(resolve:ODOO_API_USERNAME)%'
password: '%env(resolve:ODOO_API_PASSWORD)%'
First Use Case: Fetch a Record Inject the client into a service/controller:
use Ang3\Component\Odoo\Client;
class MyController
{
public function __construct(private Client $client) {}
public function index()
{
$partner = $this->client->get('res.partner', 1);
return new Response(json_encode($partner));
}
}
Dependency Injection: Use ClientRegistry to manage multiple Odoo connections.
use Ang3\Bundle\OdooBundle\ClientRegistry;
class MultiOdooService
{
public function __construct(private ClientRegistry $registry) {}
public function fetchFromConnection(string $connectionName, string $model, int $id)
{
$client = $this->registry->get($connectionName);
return $client->get($model, $id);
}
}
Autowiring: Leverage Symfony’s autowiring for named clients:
class ProductionController
{
public function __construct(
private Client $defaultClient,
private Client $productionClient // Autowired via `ang3_odoo.client.production`
) {}
}
Entity Mapping: Define Odoo entities in src/Odoo/Entity (configured in ang3_odoo.orm.paths).
namespace App\Odoo\Entity;
use Ang3\Component\Odoo\ORM\Entity;
#[Entity(model: 'res.partner')]
class Partner
{
#[Field]
public ?int $id;
#[Field]
public ?string $name;
}
Repository Pattern: Use ObjectManager to interact with entities.
use Ang3\Component\Odoo\ORM\ObjectManager;
class PartnerService
{
public function __construct(private ObjectManager $manager) {}
public function findByName(string $name): ?Partner
{
return $this->manager->find(Partner::class, ['name' => $name]);
}
}
Annotate Entities: Validate Odoo record IDs using constraints.
use Ang3\Bundle\OdooBundle\Validator\Constraints as Odoo;
class InvoiceForm
{
#[Odoo\Record(
model: 'account.move',
domains: 'expr.eq("partner_id", this.partnerId)',
connection: 'production'
)]
public ?int $invoiceId;
#[Odoo\Record(model: 'res.partner')]
public ?int $partnerId;
}
Custom Messages: Override default validation messages.
#[Odoo\Record(
model: 'res.partner',
notFoundMessage: 'Partner {{ model_id }} not found in {{ model_name }}!'
)]
public ?int $partnerId;
Check Connections: Use debug:autowiring to list available clients/managers.
php bin/console debug:autowiring Client
php bin/console debug:autowiring ObjectManager
Logging: Configure per-connection logging in ang3_odoo.connections.<name>.logger.
connections:
default:
logger: '@logger'
ORM Caching: Enable caching in ang3_odoo.orm for performance:
orm:
enabled: true
cache: true
Expression Language: Use expr in domains for dynamic filtering:
#[Odoo\Record(
model: 'account.move',
domains: 'expr.and(expr.eq("state", "posted"), expr.gt("amount_total", 1000))'
)]
Connection Errors: Handle LogicException when accessing non-existent connections:
if (!$this->registry->has('nonexistent')) {
throw new \RuntimeException('Connection not configured');
}
Ang3\Component\Odoo\Client for domain-specific logic.Odoo\Record.prePersist, postLoad).How can I help you explore Laravel packages today?