PHP code example of marshmallow / laravel-odoo
1. Go to this page and download the library: Download marshmallow/laravel-odoo library . Choose the download type require .
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
marshmallow / laravel-odoo example snippets
use Marshmallow\Odoo\Facades\Odoo;
$partners = Odoo::partners()->searchRead(
[['is_company', '=', true]],
['name', 'email', 'vat'],
limit: 50,
);
$id = Odoo::partners()->create([
'name' => 'Acme BV',
'email' => '[email protected] ',
'is_company' => true,
]);
Odoo::partners()->update($id, ['phone' => '+31 20 123 4567']);
$partner = Odoo::partners()->find($id, ['name', 'phone']);
$resource = Odoo::model('crm.lead');
$resource->find(int $id, array $fields = [], bool $loadNames = true): array; // throws MissingRecordException
$resource->get(array $ids, array $fields = [], bool $loadNames = true): array;
$resource->displayNames(array $ids): array; // [id => display_name]
$resource->exists(int $id): bool;
$resource->search(Domain|array $domain = [], ?int $limit = null, int $offset = 0, ?string $order = null): array; // ids
$resource->searchRead(Domain|array $domain = [], array $fields = [], ?int $limit = null, int $offset = 0, ?string $order = null): array;
$resource->collect(Domain|array $domain = [], array $fields = [], ?int $limit = null, int $offset = 0, ?string $order = null): Collection;
$resource->first(Domain|array $domain = [], array $fields = [], ?string $order = null): ?array;
$resource->searchCount(Domain|array $domain = []): int;
$resource->chunk(int $size, Closure $callback, Domain|array $domain = [], array $fields = [], ?string $order = null): bool;
$resource->lazy(Domain|array $domain = [], array $fields = [], int $chunkSize = 100, ?string $order = null): LazyCollection;
$resource->readGroup(Domain|array $domain, array $groupBy, array $aggregates = ['__count'], array $having = [], ?int $limit = null, int $offset = 0, ?string $order = null): array;
$resource->nameSearch(string $name, Domain|array $domain = [], ?int $limit = null, string $operator = 'ilike'): array; // [id => name]
$resource->create(array $values): int;
$resource->createMany(array $valuesList): array; // ids
$resource->update(int|array $ids, array $values): bool; // write
$resource->delete(int|array $ids): bool; // unlink
$resource->archive(int|array $ids): bool; // action_archive
$resource->unarchive(int|array $ids): bool; // action_unarchive
$resource->hasAccess(string $operation, array $ids = []): bool; // has_access: read, write, create, unlink
$resource->fields(array $attributes = []): array; // fields_get
$resource->call(string $method, array $params = [], array $ids = []): mixed;
use Marshmallow\Odoo\Resources\Invoices;
Odoo::partners()->chunk(500, function (array $partners, int $page) {
// ...
});
foreach (Odoo::invoices()->lazy(Invoices::customerInvoices(), ['name', 'amount_total']) as $invoice) {
// ...
}
Odoo::invoices()->readGroup(Invoices::customerInvoices(), ['partner_id'], ['amount_total:sum', '__count'], order: 'amount_total:sum desc');
Odoo::invoices()->call('action_post', ids: [$invoiceId]);
Odoo::partners()->call('name_search', ['name' => 'acme', 'limit' => 5]);
$dutch = Odoo::products()->withLang('nl_NL'); // withContext(['lang' => 'nl_NL'])
$dutch->find($id, ['name', 'description_sale']);
Odoo::invoices()->withCompany(2)->create([...]); // company_id + allowed_company_ids
Odoo::partners()->withTimezone('Europe/Amsterdam');
Odoo::partners()->withContext(['default_customer_rank' => 1]);
foreach (Odoo::partners()->withArchived()->lazy([], ['id', 'email', 'ref', 'active']) as $partner) {
// ...
}
Odoo::partners()->fields(['type', 'string', '
use Marshmallow\Odoo\Resources\Invoices;
use Marshmallow\Odoo\Support\Commands;
$invoiceId = Odoo::invoices()->create([
'move_type' => 'out_invoice',
'partner_id' => $partnerId,
'invoice_line_ids' => [
Commands::create(['product_id' => $productId, 'quantity' => 2, 'price_unit' => 19.95, 'tax_ids' => Commands::set([$taxId])]),
],
]);
Odoo::invoices()->post($invoiceId);
Odoo::invoices()->paymentState($invoiceId); // not_paid, in_payment, paid, partial, reversed
$open = Odoo::invoices()->searchRead(
Invoices::customerInvoices()->where('payment_state', 'not_paid'),
['name', 'amount_residual'],
);
Odoo::products()->update($productId, ['taxes_id' => Commands::set([$taxId])]);
use Marshmallow\Odoo\Support\Domain;
$domain = Domain::make()
->where('is_company', true)
->where('country_id.code', '=', 'NL')
->whereIn('id', [1, 2, 3])
->whereNotNull('email')
->whereILike('name', 'acme')
->orWhere('ref', 'ACME');
$domain->toArray();
// ['|', '&', '&', '&', '&', ['is_company', '=', true], ['country_id.code', '=', 'NL'], ['id', 'in', [1, 2, 3]], ['email', '!=', false], ['name', 'ilike', 'acme'], ['ref', '=', 'ACME']]
Domain::make()
->where('is_company', true)
->where(fn (Domain $d) => $d->where('country_id.code', 'NL')->orWhere('country_id.code', 'BE'))
->whereNot(fn (Domain $d) => $d->whereNull('email'))
->whereBetween('create_date', '2026-01-01', '2026-12-31');
Odoo::api()->call('res.partner', 'search_read', ['domain' => [], 'fields' => ['name'], 'limit' => 10]);
Odoo::api()->version(); // GET /web/version, raw payload
Odoo::api()->versionLabel(); // "19.0+e"
Odoo::api()->majorVersion(); // 19
Odoo::api()->contextGet(); // uid, lang, tz of the API key user
Odoo::enabled(); // config('odoo.enabled')
use Marshmallow\Odoo\Exceptions\ValidationException;
try {
Odoo::partners()->create(['email' => 'not-an-email']);
} catch (ValidationException $exception) {
$exception->getMessage(); // Odoo's message
$exception->odooName(); // odoo.exceptions.ValidationError
$exception->arguments(); // Odoo's arguments list
$exception->debug(); // server traceback, when Odoo sends one
$exception->payload; // the full decoded error body
$exception->response; // the Illuminate HTTP response
}
use Marshmallow\Odoo\Facades\Odoo;
use Marshmallow\Odoo\Testing\RecordedCall;
$odoo = Odoo::fake([
'res.partner/search_read' => [['id' => 7, 'name' => 'Acme']],
'res.partner/create' => [8],
]);
// ... run the code under test ...
$odoo->assertCalled('res.partner', 'create', fn (RecordedCall $call): bool => $call->params['vals_list'][0]['name'] === 'Acme');
$odoo->assertCalledTimes('res.partner', 'search_read', 1);
$odoo->assertNotCalled('res.partner', 'unlink');
$odoo->assertNothingCalled();
$odoo->respond('res.partner', 'read', fn (RecordedCall $call): array => array_map(
fn (int $id): array => ['id' => $id, 'name' => "Partner {$id}"],
$call->ids,
));
Http::fake([
'company.odoo.com/json/2/res.partner/search_read' => Http::response([['id' => 7, 'name' => 'Acme']]),
'company.odoo.com/json/2/*' => Http::response(['name' => 'odoo.exceptions.AccessError', 'message' => 'No access'], 403),
]);
namespace App\Odoo;
use Marshmallow\Odoo\Resources\Resource;
class Leads extends Resource
{
protected string $model = 'crm.lead';
public function won(): array
{
return $this->searchRead([['stage_id.is_won', '=', true]], ['name', 'partner_id']);
}
}
// config/odoo.php
'resources' => [
'leads' => App\Odoo\Leads::class,
],
Odoo::leads()->won();
// or, without touching the config:
Odoo::macro('leads', fn () => new App\Odoo\Leads($this->api()));
bash
php artisan odoo:doctor
bash
php artisan vendor:publish --tag="odoo-config"