consilience/laravel-odoo-api-client

Laravel 对 Odoo API 的提供者

0.11.0 2019-04-22 17:37 UTC

This package is auto-updated.

Last update: 2024-08-29 04:20:16 UTC


README

支持 Laravel 5.7 和 Odoo 7 (OpenERP 7)

Latest Stable Version Total Downloads Latest Unstable Version License

简介

本包的目的是从 Laravel 内部方便地访问 OpenERP/Odoo XML-RPC API。只需设置一些配置,从 OdooApi 门面获取一个客户端,然后传递一些数据即可。

理想情况下,这将是两部分:一个 API 包和一个 Laravel 包装器。这可以稍后完成,但到目前为止这已经满足我们的需求,并且 Laravel 提供的一些辅助器使得事情运行得更加顺畅(集合,数组/对象点符号访问)。

安装

通过 composer

composer require consilience/laravel-odoo-api-client

注意:待发布到 packagist,需要在 composer.json 中添加以下条目以定位此包

    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/consilience/laravel-odoo-api-client.git"
        }
        ...
    ]
    ...

发布配置

使用 Laravel artisan 命令发布 config\odoo-api.php

artisan vendor:publish --provider="Consilience\OdooApi\OdooServiceProvider"

.env.example 中可以找到 .env 的示例设置。

您可以在 config\odoo-api.php 中添加多个配置集,并在您的应用程序中同时使用它们。配置集名称通过 OdooApi::getClient('config-name') 传递。

示例

一个非常简单的示例

// This facade is auto-discovered for Laravel 5.6+

use OdooApi;

// The default config.
// getClient() will take other configuration names.

$client = OdooApi::getClient();

// Note the criteria is a nested list of scalar values.
// The datatypes will converted to the appropriate objects internally.
// You can mix scalars and objects here to force the datatype, for example
// ['name', $client->stringValue('ilike'), 'mich']

$criteria = [
    ['name', 'ilike', 'mich'],
];

// First 10 matching IDs

$client->search('res.partner', $criteria, 0, 10, 'id desc')->value()->me['array']

// Total count for the criteria.

$client->searchCount('res.partner', $criteria);

// Read the complete details of two specific partners.

$client->read('res.partner', [17858, 17852])->value()->me['array']

如果您对 XML-RPC 客户端有特定的要求,例如要添加 SSL 证书,则可以使用以下方式获取客户端实例

$xmlRpcClient = $client->getXmlRpcClient($type);

其中 $type 通常为 'db'、'common' 或 'object'。

您可以从头开始构造自己的消息,如上所示,并且 $client 中有辅助方法可以将原生 PHP 数据类型转换为 XML RPC 值对象,以及从 XML RPC 值对象转换回原生 PHP 数据类型。但是,您应该能够让客户端在后台处理所有这些转换 - 只需给它数组/字符串/整数等数据,然后返回模型和数组。

搜索条件

搜索条件是搜索术语和逻辑运算符的数组,用波兰表示法表达。

用于比较搜索术语的逻辑运算符是

  • & - 逻辑 AND
  • | - 逻辑 OR
  • ! - 逻辑 NOT

每个搜索术语的形式如下

[field_name, operator, value]

搜索术语运算符是

  • =
  • !=
  • >
  • >=
  • <
  • <=
  • like
  • ilike
  • in
  • not in
  • child_of - 记录是给定记录的子记录或孙记录,
  • parent_left
  • parent_right

示例:搜索名称类似于 'Fred%' 或 'Jane%' 且合作伙伴 ID 为 1 或 2 的记录,将如下所示

[
    '&',
    '|',
    ['name', 'like', 'Fred%'],
    ['name', 'like', 'Jane%'],
    ['partner_id', 'in', [1, 2]],
]

波兰表示法从内到外工作。第一个 & 运算符取下两个术语并将它们进行 AND 运算。两个术语中的第一个是 | 运算符。然后 | 运算符取下两个术语并将它们进行 OR 运算,从而得到一个单一的条件,该条件作为输入传递给 'AND'。最后一个术语作为 'AND' 条件输入。结果是

(name like 'Fred%' or name like 'Jane%') and partner_id in (1, 2)

查询方法

以下方法受到支持,并将返回一个集合

  • search() - 整数集合
  • searchRead() - 模型集合
  • read() - 模型集合
  • getResourceIds - 整数集合
  • fieldsGet() - 数组集合

以下辅助函数返回原生 PHP 类型

  • searchCount - 整数
  • getResourceId - 整数
  • unlink - 布尔值
  • create - 整数
  • write - 布尔值

所有 read()searchRead() 方法将返回一组模型。默认模型将是 Consilience\OdooApi\Model,但也可以指定其他模型。odoo-api.php 配置提供了一个数组设置,用于将 OpenERP 模型名称映射到模型类名称以进行实例化。可以通过使用 $client->addMapping('odoo.model.name', \FQDN\Class\name::class) 在客户端添加更多映射。

注意,对于小于 8.0 版本的 Odoo(OpenERP),searchRead 将模拟服务器的 search_read,但对于 8.0 版本以上的 Odoo,则使用原生的 search_read

读取选项

read() 方法接受一个选项数组,它在 OpenERP/Odoo 版本之间差异很大。该包目前不尝试处理这一点。

例如,要限制读取到命名属性,以下格式被使用

  • OpenERP 7: $client->read('account.invoice', [123], ['type', 'partner_id']);
  • OpenERP 8: $client->read('account.invoice', [123], ['fields' => ['type', 'partner_id']]);
  • OpenERP 10: $client->read('account.invoice', [123], ['attributes' => ['type', 'partner_id']]);

这使得在 API 上寻找帮助变得困难,因为许多文章没有明确说明 OpenERP/Odoo 版本号。

设置关系

有创建关系数据的助手。以下是一个简单的示例,用一组新的发票替换属于合作伙伴的所有发票

$invoiceIds = ... // array or collection of resource IDs for the invoices to link

$response = $client->write(
    'res.partner',
    $partnerResourceId,
    [
        'invoice_ids' => $client->relationReplaceAllLinks($invoiceIds),
        
        // other optional fields and relations can be set here as nornmal
    ]
);

设置关系的一般方法是设置关系(在本例中为 invoice_ids)到一个包含 ID 列表及其对这些 ID 执行操作说明的数据结构。

这里的 relationReplaceAllLinks() 生成数据结构以指导 Odoo 用新的 $invoiceIds(一个数组)替换 res.partner 与任何他们拥有的发票之间的所有链接。您可以自己构造这些数据结构,或使用以下助手

// Relate a resource.
$client->relationCreate(array $resourceIds)

// Update a related resource.
// e.g. change the product on an invoice line for an invoice
relationUpdate(int $resourceId, array $values)

// Delete a related resource completely.
// e.g. delete an invoice line on an invoice
relationDelete(int $resourceId)

// Remove the relation to a related resource, but leave the resource intact.
// e.g. remove an invoice from a contact so it can be adde to a new contact
relationRemoveLink(int $resourceId)

// Add a resource to a relation, leaving existing relations intact.
// e.g. add an additional line to an invoice. 
relationAddLink(int $resourceId)

// Remove all relations to a resource type.
// e.g. remove all invoices from a contact, before the contatc can is deleted.
relationRemoveAllLinks()

// Replace all relations with a new set of relations.
// e.g. remove all invoices from contact, and give them a new bunch of invoices
// to be responsible for. 
relationReplaceAllLinks(iterable $resourceIds)

非 CRUD 请求

有助手函数提供 readwriteunlinksearch 功能,但您也可以访问较低级别的其他 API 方法。例如,可以使用销售订单的 message_post 函数向销售发票添加备注。下面的示例展示了如何做到这一点。

use OdooApi;

$client = OdooApi::getClient();

// Resource and action, the remote RPC function.
// Note that the message_post() function for each resource type is
// different, i.e. this is not something that can be genereralised
// in the API.
// This starts to build the request message and addes the first
// few positional parameters and authentication details.

$msg = $client->getBaseObjectRequest('sale.order', 'message_post');

// Further positional parameters.
// This is for an Odoo 7.0 installation. Other versions may differ.

$msg->addParam($client->nativeToValue([$orderId])); // Resource(s) ID
$msg->addParam($client->nativeToValue($text_message)); // Body
$msg->addParam($client->nativeToValue(false)); // Subject
$msg->addParam($client->nativeToValue('comment')); // Subtype
$msg->addParam($client->nativeToValue(false)); // Partner IDs to send a copy to

// Send the message.

$response = $client->getXmlRpcClient('object')->send($msg);

// If you want to inspect the result, then this will give you
// what the Odoo message_post() function returns.

$result = $client->valueToNative($response->value());

加载函数

Odoo 提供了一个处理资源加载的加载器 API。该包提供了 load()loadOne() 方法来访问该 API。

加载器使用 id 作为外部 ID。如果资源已存在,它将找到资源并更新它;否则,如果资源不存在,它将创建资源。

列表中的每个资源都可以指定不同的字段,但所有字段都必须为同一资源模型。

    // Load one or more partners.

    $loadResult = $client->load('res.partner', [
        [
            "name" => "JJ Test",
            "active" => "TRUE",
            "type" => "developer",
            "id" => "external.partner_12345",
        ],
        // Further records for this model...
    ]);

响应将是一个包含两个元素的数组,idsmessages,两者都是集合。

ids 集合将包含任何更新或创建的资源 内部 ID。messages 集合将包含任何失败更新或资源创建的验证错误。对于单个失败的记录可能有多个消息。

// Example response with no errors and two resources updated or created.

array:2 [
  "ids" => Collection {
    #items: array:2 [
      0 => 7252
      1 => 7251
    ]
  }
  "messages" => Collection {
    #items: []
  }
]

// Example with oen validation error.
// Note no records are loaded at all if any record fails validation.

array:2 [
  "ids" => Collection {
    #items: []
  }
  "messages" => Collection {
    #items: array:1 [
      0 => array:5 [
        "field" => "year"
        "rows" => array:2 [
          "to" => 1
          "from" => 1
        ]
        "record" => 1
        "message" => "'2019x' does not seem to be an integer for field 'My Year'"
        "type" => "error"
      ]
    ]
  }
]

尽管记录键可以在记录之间有所不同,但 Odoo API 不支持内部这一点。该包通过将具有相同键的记录分组并分组加载来解决此问题。这意味着一个组中的验证错误不会阻止另一个组中的记录加载,因此结果可以是失败和加载记录的混合。

在 Odoo 中,对于不可恢复的错误(例如数据库完整性约束违反),将抛出异常。

loadOne() 方法以类似的方式工作,但它只接受一个记录进行加载。它将返回一个包含整数 内部 IDid 元素,如果记录失败加载则返回 null,以及一个包含消息的集合。

待办事项

  • 尚未测试 date 类型的转换。理想情况下,我们会支持 Carbon 2 以发送日期并获取返回的日期。
  • 测试。当时间受限时,总是测试被遗忘。它们需要在Laravel环境中运行,因此需要相应的助手。
  • 如果能将其拆分为非Laravel包,并为它添加一个独立的Laravel包装器,那就很棒了。但是集合太好了,所以这可能不会发生。
  • 一些Odoo版本特定数据结构的助手方法。例如,为版本7、8和10的read指定要检索的字段列表引入了新的结构。客户端类在此阶段可能会变得有些繁琐,因此将一些XML-RPC特定的内容(消息创建、数据转换)移动到单独的连接类中会更好。
  • 位置参数构建助手。
  • 一些更具体的异常。