## Getting Started
### Minimal Setup
1. **Installation**
```bash
composer require ang3/php-odoo-orm
Add the autoloader to your project (Composer handles this automatically).
First Connection
use Ang3\Odoo\OdooConnection;
$connection = new OdooConnection(
'http://your-odoo-instance.com',
'database_name',
'username',
'password'
);
First Query (Fetching Records)
$model = $connection->getModel('res.partner'); // Odoo model name
$partners = $model->findAll(); // Fetch all records
First Write Operation
$partner = $model->create([
'name' => 'John Doe',
'email' => 'john@example.com'
]);
Searching Records (Fixed in v0.1.9)
// Use searchAll() for advanced searches (now fully functional in v0.1.9)
$results = $model->searchAll('John', ['name', 'email']);
Note: The searchAll() method was previously fixed in v0.1.9 to properly handle multi-field searches with Odoo's XML-RPC API.
// Create
$record = $model->create(['field1' => 'value1']);
// Read
$record = $model->find($id);
$records = $model->findAll(['filter' => ['active' => true]]);
// Update
$record->name = 'Updated Name';
$record->save();
// Delete
$model->delete($id);
// Basic filter
$activePartners = $model->findAll([
'domain' => [['active', '=', true]]
]);
// Search with fields (now reliable in v0.1.9)
$results = $model->searchAll('John', ['name', 'email']); // Search across multiple fields
// Load related records (e.g., orders for a partner)
$partner = $model->find($id);
$orders = $partner->orders->findAll(); // Assumes 'orders' is a defined relation
$batchSize = 100;
$offset = 0;
do {
$records = $model->findAll([
'limit' => $batchSize,
'offset' => $offset
]);
// Process records...
$offset += $batchSize;
} while (count($records) > 0);
// Call a custom Odoo method (e.g., `action_confirm`)
$result = $model->execute('action_confirm', [[$id]]);
Bind the connection to Laravel’s container for dependency injection:
// config/app.php
'bindings' => [
Ang3\Odoo\OdooConnection::class => function ($app) {
return new OdooConnection(
config('odoo.url'),
config('odoo.database'),
config('odoo.username'),
config('odoo.password')
);
},
];
Create a facade for cleaner syntax:
// app/Facades/Odoo.php
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class Odoo extends Facade {
protected static function getFacadeAccessor() {
return 'odoo.connection';
}
}
Usage:
$partners = Odoo::model('res.partner')->findAll();
$searchResults = Odoo::model('res.partner')->searchAll('John', ['name', 'email']);
Hook into Odoo events (e.g., after record creation) using Laravel’s event system:
// Listen for Odoo model events
$model->on('created', function ($record) {
// Trigger Laravel event or logic
});
Cache frequent queries to reduce API calls:
$cacheKey = "odoo_partners_active";
$partners = Cache::remember($cacheKey, now()->addHours(1), function () use ($model) {
return $model->findAll(['domain' => [['active', '=', true]]]);
});
Model Naming
account.move).account_move) in method calls. Verify case sensitivity:
// Correct
$model = $connection->getModel('account_move');
// Incorrect (may fail silently)
$model = $connection->getModel('AccountMove');
Field Names vs. Database Fields
partner_id vs. user_id).Rate Limiting
try {
$result = $model->find($id);
} catch (\Exception $e) {
if ($e->getCode() === 400) { // Example: Bad request
retry($attempts++, function () use ($model, $id) {
return $model->find($id);
}, 1000); // Retry after 1s
}
}
Authentication Failures
$connection = new OdooConnection(..., ..., ..., ..., true); // Enable debug
Check logs for XML-RPC errors.Large Payloads
write() for partial updates:
$model->write([$id], ['field1' => 'value1']); // Update single field
Search Method Fix (v0.1.9)
searchAll() method was fixed in v0.1.9 to properly handle multi-field searches.search() for multi-field searches, as they may not work as expected.// Correct (v0.1.9+)
$results = $model->searchAll('John', ['name', 'email']);
// Avoid (may not work as intended)
$results = $model->search('John', ['name']);
Enable Verbose Logging
$connection->setDebug(true);
// Check logs for raw XML-RPC requests/responses.
Inspect Raw XML-RPC Calls Use a tool like Postman or SoapUI to manually test endpoints before debugging the PHP code.
Handle Odoo Exceptions
Catch Ang3\Odoo\Exception\OdooException for Odoo-specific errors:
try {
$model->create([...]);
} catch (\Ang3\Odoo\Exception\OdooException $e) {
// Parse Odoo error messages (often in $e->getMessage())
}
Check Odoo Server Logs
/var/log/odoo/odoo-server.log (default path).xmlrpc or request keywords.Search Method Debugging (v0.1.9)
searchAll() behaves unexpectedly, verify:
'John' for partial matches).// Ensure 'email' is a valid field for the model
$results = $model->searchAll('John', ['name', 'email']);
Ang3\Odoo\Model to add domain-specific logic:
class CustomPartnerModel extends \Ang3\Odoo\Model {
public function getActivePartnersWithEmail() {
return $this->searchAll('', ['name', 'email'], [
How can I help you explore Laravel packages today?