Aimeos frontend JSON REST API package for e-commerce projects
aimeos / ai-client-jsonapi Goto Github PK
View Code? Open in Web Editor NEWAimeos frontend JSON API
License: GNU Lesser General Public License v3.0
Aimeos frontend JSON API
License: GNU Lesser General Public License v3.0
Environment
Version : 2020.10
Operating system: linux ubuntu on docker
Describe the bug
Trying to filter products by category and sort them, at the same time
To Reproduce
/jsonapi/product?sort=price&include=price,media
this request is properly sorted by price
/jsonapi/product?sort=price&filter[f_catid]=4&include=price,media
this request is not properly sorted by price
the sort property is ignored when the filter category is present
Expected behavior
Should sort by price and filter by category?
Screenshots
na
Additional context
My issue arose with trying to send a DELETE request to clear the basket.
First add some products with a POST to the product url . /jsonapi/basket?id=default&related=product { product data }
Store the response to my local basket model including the 'links' to modify the basket later.
Send a DELETE to the provided basket links.self.href , error bad JSON in response.
The issue I found was the basket self link provided by the first request was incorrect. Here is the link being provided by the Add Product basket response in links.self.href -> /jsonapi/basket?id=default&related=product
The correct link in side links.self.href should be /jsonapi/basket?id=default
"name": "aimeos/ai-client-jsonapi",
"version": "2021.07.1",
I am facing an issue right now related to customer addresses, the patch request is deleting the addresses on update.
previously I used 2024.04.01 for all packages but was facing context and auth issues for supplier users (admin group), yesterday the 2024.07.x-dev was live so updated all packages to 2024.07.1 and for aimeos/aimeos-laravel used the 2024.07.x-dev, now addresses are removed on patch request
this POST request is creating the address
https://local.droppe.com/jsonapi/default/customer?id=4058&related=address
Body: {"data":[{"attributes":{"customer.address.address1":"address 1","customer.address.postal":"postal 1","customer.address.city":"city1","customer.address.countryid":"fi","customer.address.addressdetails":"","customer.address.deliverynotes":"notes1","customer.address.company":"","customer.address.vatid":"","customer.address.email":"","customer.address.telephone":"+3582323223","customer.address.position":0}}]}
when i try to update the same address returned from the post request via PATCH it just removes it
https://local.droppe.com/jsonapi/default/customer?id=4058&related=address&relatedid=6124
Body: {"data":{"attributes":{"customer.address.address1":"address 11","customer.address.postal":"postal 11","customer.address.city":"city 11","customer.address.countryid":"fi","customer.address.addressdetails":"","customer.address.deliverynotes":"notes11","customer.address.telephone":"+35823232323"}}}
Hi!
I think more methods should be added here:
"basket/product": {
"href": "<?= $this->url( $target, $cntl, $action, ['resource' => 'basket', 'id' => $basketId, 'related' => 'product'], [], $config ); ?>",
"allow": ["POST"]
},
client/jsonapi/src/Client/JsonApi/Basket/Product/Standard.php allows multiple items to be deleted by a body with an array of Objects with an id attribute.
This probably is true. for other methods and other basket types.
Environment
Describe the bug
Per the docs the frontend jsonapi customer should be able to set the customer password on post. It does not. https://aimeos.org/docs/2020.x/frontend/jsonapi/customer/#create-new-customer
To Reproduce
Steps to reproduce the behavior:
Follow the docs to make a json post request of a user with a password.
Expected behavior
A user should have the password set. Instead it generates the random password.
Screenshots
na
Additional context
I was able to solve this by replacing the frontend controller and modifying the "add" function. The password field gets unset down the line in the Customer Manager. To solve this i used the frontend controller to first grab the password, then apply it at the end. This seems to be what you attempted but the value gets unset if you do not store it first.
Also, In the documentation for configurations there is a mistake on "name" parameter.
https://aimeos.org/docs/2020.x/config/controller-frontend/customer/#name
It should be
controller/frontend/customer/name = Mycustomer
and not
controller/jobs/frontend/customer/name = Mycustomer
Would it be possible to allow including nested resources as defined in the jsonapi specification.
For example, when having a single product page where we would also want to display some information about the supplier, it's currently only possible to include the supplier resource /jsonapi/default/product?id=1&include=supplier
. However, we would also probably want to show the supplier image and description which currenlty requires a new (and dependent) request /jsonapi/default/supplier?id=<id from previous request>&include=text,media
.
The jsonapi spec allows nested includes, which would mean that this scenario could be solved via /jsonapi/default/product?id=1&include=supplier,supplier.text,supplier.media
.
This would greatly simplify a lot of data fetching when using the api.
Although I'm not too familiar with the aimeos codebase yet it seems like this should be possible to implement in the aimeos data architechture,
simply iterating over the different domains that need to be included and searching for the related resources.
Hi
could you help me for this issue
I need to change "Item with ID "44" in "product.id" not found" text to Product not found.
for this api https://example.loc/test/jsonapi/product?id=44
but I can't find it from where coming this text
I tired add this translation in my ext/example/lib/custom/i18n/en.po file and run gettext command
but was not changed
msgid "Item with ID \"%2$s\" in \"%1$s\" not found"
msgstr "You will need to upgrade the application to view this product \"%2$s\" in \"%1$s\""
{
"meta": {
"total": 0,
"prefix": null,
"content-baseurl": "http://example.loc"
, "csrf": {
"name": "_token",
"value": "M3bMz4dsfEfvCekaYhUulpxkBnFUiV37rMj"
}
},
"links": {
"self": "https://example.loc/test/jsonapi/product?id=44&page%5Boffset%5D=0"
}
,"errors": [{"title":"Item with ID \"44\" in \"product.id\" not found"}]
}
and for others translations working good
Hi,
Can you please explain how to authenticate a user and create a new customer using the API? I need to implement login and new user registration using an API in my APPs.
Where does the ajax call URL come from in JavaScript?
var url = result['links']['customer']['href']; // derived from the OPTIONS response
In the OPTIONS response, links doesn't have "customer" with "href" and I tried "self", but it is not working. Also, in "data.links.self.href" I tried, but it doesn't have a post method and it not works.
I have been using a function with the Basket and Customer to match the "included" to their "data.relationships". Since each type and id are unique in the included , those become the index to finding the related data.
Finally got around to the Order history and this function does not work because the mapping ID are different.
Since the id used in the Order Relationships section depend on attributes like ''order.base.product.id", it is nearly impossible to map these without an intimate knowledge of all the fields in the API.
Either the included order/base/product id should be the product id, Or the relationships id should be the position index.
The attribute "links.self" are inconsistent across domains. Besides "Self" the other attributes always provide an object with href and methods. Only with the "self" of links an object is inconsistent.
Some domains don't provide this link object for the "self", just a string (Product or Customer). Other domains like Basket do provide a link object.
Fetch a Catalog https://aimeos.org/docs/2021.x/frontend/jsonapi/catalog/#fetch-products
{
"meta": {
"total": 3
},
"links": {
"self": "http:\/\/localhost:8000\/jsonapi\/product?include=attribute%2Cmedia%2Cprice%2Cproduct%2Cproduct%2Fproperty%2Ctext&page%5Boffset%5D=0"
},
vs
Fetch a Basket https://aimeos.org/docs/2021.x/frontend/jsonapi/baskets/#fetch-the-basket
{
"meta": {
"total": 1,
"prefix": null,
"content-baseurl": "/",
"csrf": {
"name": "_token",
"value": "..."
}
},
"links": {
"self": {
"href": "http://localhost:8000/jsonapi/basket",
"allow": ["DELETE","GET","PATCH"]
}
https://aimeos.org/docs/Developers/Client/JSONAPI/Fetch_items#Return_specific_fields_only
The example for fetching the specific fields is incorrect
Its not:
var params = { fields: 'product.id,product.label' };
but:
"fields": { "product": "product.id,product.label" }
At the moment (in 2018.10), if you get the basket via the Jsonapi and a basket plugin throws an error the POST is removed from allowed actions for the basket, but the error message is not added to the errors.
I think it would be better if the error messages from basket plugins were added to the Jsonapi response to have a message to show to the user why the basket is not ready to be finished.
https://aimeos.org/docs/latest/frontend/jsonapi/catalog/#get-products-by-category
I have several product with multiple catalog tags. They all have a Default category , some have Promotion type 'home' and some have promotion type of the category name. Some have both promotions of 'home' and category name.
curl -X GET '/jsonapi/product?site=default&filter%5Bf_listtype%5D=promotion&filter%5Bf_catid%5D=1'
This should retrieve the 'promotion' category of 'home' = 1.
{
"meta": {
"total": 33,
"prefix": null,
"content-baseurl": "/aimeos"
I receive 33 result count, however there are 70+ items in home promotions category.
curl -X GET '/jsonapi/product?site=default&filter%5Bf_listtype%5D=promotion&filter%5Bf_catid%5D=2'
Promotions of type Category 2: I receive 0 results count, however there are 3 items in that category. According to the admin /admin/default/jqadm/get/catalog/2?locale=en#product > Filter by type promotion
/jsonapi/product?site=default&filter[f_listtype]=promotion&filter[f_catid]=3
Promotions of type Category 3. I receive 2 result count, my count is 8
The products are all enabled. I have stock quantity checks off. Ran php artisan aimeos:jobs "index/rebuild"
aimeos/ai-client-jsonapi 2021.07.x-dev 0c764ae
2021.07.x-dev 0c764ae
/jsonapi/product?site=default&sort=-ctime&include=attribute,media,price,price/property,product,product/property,text,catalog,supplier,stock&page[offset]=0&page[limit]=4&filter[f_catid]=2&filter[f_listtype]=promotion
{
"meta": {
"total": 0,
"prefix": null,
"content-baseurl": "/aimeos
SELECT * FROM mshop_index_catalog
WHERE catid
LIKE '2' AND listtype
LIKE 'promotion'
114 | 1. | 2 | promotion | 0 | 2021-09-29 05:56:39
142 | 1. | 2 | promotion | 0 | 2021-09-29 05:56:39
143 | 1. | 2 | promotion | 0 | 20
3 Items expected.
$filter from Aimeos\Controller\Frontend\Product\Standard function search
Aimeos\MW\Criteria\SQL {#455
-conn: Aimeos\MW\DB\Connection\DBAL {#377
-connection: Doctrine\DBAL\Connection {#381
#_conn: Doctrine\DBAL\Driver\PDO\Connection {#384
inTransaction: false
attributes: {
CASE: NATURAL
ERRMODE: EXCEPTION
AUTOCOMMIT: 1
PERSISTENT: false
DRIVER_NAME: "mysql"
SERVER_INFO: "Uptime: 31864 Threads: 2 Questions: 62478 Slow queries: 0 Opens: 145 Open tables: 138 Queries per second avg: 1.960"
ORACLE_NULLS: NATURAL
CLIENT_VERSION: "mysqlnd 7.4.20"
SERVER_VERSION: "5.5.5-10.5.10-MariaDB-1:10.5.10+maria~focal"
STATEMENT_CLASS: array:2 [
0 => "Doctrine\DBAL\Driver\PDO\Statement"
1 => []
]
EMULATE_PREPARES: 1
CONNECTION_STATUS: "mariadb via TCP/IP"
DEFAULT_FETCH_MODE: BOTH
}
}
#_config: Doctrine\DBAL\Configuration {#378
#_attributes: []
}
#_eventManager: Doctrine\Common\EventManager {#379
-_listeners: []
}
#_expr: Doctrine\DBAL\Query\Expression\ExpressionBuilder {#382
-connection: Doctrine\DBAL\Connection {#381}
}
-autoCommit: true
-transactionNestingLevel: 0
-transactionIsolationLevel: null
-nestTransactionsWithSavepoints: false
-params: array:14 [
"adapter" => "mysql"
"host" => "mariadb"
"port" => "3306"
"socket" => ""
"stmt" => array:1 [
0 => "SET SESSION sort_buffer_size=2097144; SET NAMES 'utf8mb4'; SET SESSION sql_mode='ANSI'"
]
"limit" => 3
"defaultTableOptions" => array:2 [
"charset" => "utf8mb4"
"collate" => "utf8mb4_unicode_ci"
]
"driverOptions" => array:4 [
8 => 0
3 => 2
11 => 0
17 => false
]
"driver" => "pdo_mysql"
]
-platform: null
#_schemaManager: null
#_driver: Doctrine\DBAL\Driver\PDO\MySQL\Driver {#380}
-isRollbackOnly: false
#defaultFetchMode: 2
}
-txnumber: 0
-stmts: array:1 [
0 => "SET SESSION sort_buffer_size=2097144; SET NAMES 'utf8mb4'; SET SESSION sql_mode='ANSI'"
]
-params: array:14 [
"adapter" => "mysql"
"host" => "mariadb"
"port" => "3306"
"socket" => ""
"stmt" => array:1 [
0 => "SET SESSION sort_buffer_size=2097144; SET NAMES 'utf8mb4'; SET SESSION sql_mode='ANSI'"
]
"limit" => 3
"defaultTableOptions" => array:2 [
"charset" => "utf8mb4"
"collate" => "utf8mb4_unicode_ci"
]
"driverOptions" => []
"driver" => "pdo_mysql"
]
}
-conditions: Aimeos\MW\Criteria\Expression\Combine\SQL {#456
-expressions: array:4 [
0 => Aimeos\MW\Criteria\Expression\Compare\SQL {#447
-conn: Aimeos\MW\DB\Connection\DBAL {#377}
-operator: "!="
-name: "index.catalog.id"
-value: null
-exprPlugins: []
}
1 => Aimeos\MW\Criteria\Expression\Combine\SQL {#446
-expressions: array:3 [
0 => Aimeos\MW\Criteria\Expression\Combine\SQL {#395
-expressions: array:2 [
0 => Aimeos\MW\Criteria\Expression\Combine\SQL {#394
-expressions: array:1 [
0 => Aimeos\MW\Criteria\Expression\Compare\SQL {#393
-conn: Aimeos\MW\DB\Connection\DBAL {#377}
-operator: "=="
-name: "product.status"
-value: 1
-exprPlugins: []
}
]
-operator: "&&"
}
1 => Aimeos\MW\Criteria\Expression\Compare\SQL {#392
-conn: Aimeos\MW\DB\Connection\DBAL {#377}
-operator: "=="
-name: "1"
-value: "1"
-exprPlugins: []
}
]
-operator: "&&"
}
1 => Aimeos\MW\Criteria\Expression\Combine\SQL {#442
-expressions: array:3 [
0 => Aimeos\MW\Criteria\Expression\Compare\SQL {#396
-conn: Aimeos\MW\DB\Connection\DBAL {#377}
-operator: "=="
-name: "product.type"
-value: "event"
-exprPlugins: []
}
1 => Aimeos\MW\Criteria\Expression\Compare\SQL {#397
-conn: Aimeos\MW\DB\Connection\DBAL {#377}
-operator: "=="
-name: "product.datestart"
-value: null
-exprPlugins: []
}
2 => Aimeos\MW\Criteria\Expression\Compare\SQL {#439
-conn: Aimeos\MW\DB\Connection\DBAL {#377}
-operator: "<="
-name: "product.datestart"
-value: "2021-09-29 07:11:00"
-exprPlugins: []
}
]
-operator: "||"
}
2 => Aimeos\MW\Criteria\Expression\Combine\SQL {#445
-expressions: array:2 [
0 => Aimeos\MW\Criteria\Expression\Compare\SQL {#443
-conn: Aimeos\MW\DB\Connection\DBAL {#377}
-operator: "=="
-name: "product.dateend"
-value: null
-exprPlugins: []
}
1 => Aimeos\MW\Criteria\Expression\Compare\SQL {#444
-conn: Aimeos\MW\DB\Connection\DBAL {#377}
-operator: ">="
-name: "product.dateend"
-value: "2021-09-29 07:11:00"
-exprPlugins: []
}
]
-operator: "||"
}
]
-operator: "&&"
}
2 => Aimeos\MW\Criteria\Expression\Compare\SQL {#451
-conn: Aimeos\MW\DB\Connection\DBAL {#377}
-operator: "=="
-name: "index.catalog.id"
-value: array:1 [
0 => "2"
]
-exprPlugins: []
}
3 => Aimeos\MW\Criteria\Expression\Compare\SQL {#452
-conn: Aimeos\MW\DB\Connection\DBAL {#377}
-operator: ">="
-name: "index.catalog:position("promotion",["2"])"
-value: 0
-exprPlugins: []
}
]
-operator: "&&"
}
-sortations: array:3 [
0 => Aimeos\MW\Criteria\Expression\Sort\SQL {#450
-conn: Aimeos\MW\DB\Connection\DBAL {#377}
-operator: "-"
-name: "product.ctime"
-exprPlugins: []
}
1 => Aimeos\MW\Criteria\Expression\Sort\SQL {#453
-conn: Aimeos\MW\DB\Connection\DBAL {#377}
-operator: "+"
-name: "sort:index.catalog:position("promotion",["2"])"
-exprPlugins: []
}
2 => Aimeos\MW\Criteria\Expression\Sort\SQL {#454
-conn: Aimeos\MW\DB\Connection\DBAL {#377}
-operator: "+"
-name: "product.id"
-exprPlugins: []
}
]
-sliceStart: 0
-sliceSize: 4
}
Adding an "include" to the customer get create bad links to access the sub domains (address).
sample response from the included array
{
"id": "45",
"type": "customer/address",
"attributes": {
"customer.address.id": "45",
"customer.address.address1": "Test street",
"customer.address.address2": "1",
"customer.address.address3": "",
"customer.address.birthday": null,
"customer.address.position": 1
},
"links": {
"self": {
"href": "http://localhost:8000/jsonapi/customer?id=492&related=customer%2Faddress&relatedid=45&site=default",
"allow": [
"DELETE",
"GET",
"PATCH"
]
},
"basket/address": {
"href": "http://localhost:8000/jsonapi/basket?id=default&related=address&relatedid=payment&site=default",
"allow": [
"POST"
]
}
}
}
{
"errors": [
{
"title": "Not allowed for this resource"
}
]
}
Delete is working fine. http://localhost:8000/jsonapi/customer?id=492&related=address&relatedid=45&site=default
https://website.com/jsonapi/ -OPTIONS
{
"meta": {
"prefix": null,
"content-baseurl": "http://website.com"
....
, "csrf": {
}
}
EXPECTED
"content-baseurl": "https://website.com"
+s
easily patched in the frontend, but unexpected
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.