Closed binaryfire closed 2 years ago
Lighthouse-php requires Eloquent models which we don't use for performance reasons. Thus, the package isn't compatible with Aimeos if you don't implement models for the tables Aimeos is using.
GraphQL is very good for write-heavy applications but as frontend for read-heavy e-commerce applications it's not suited and we recommend the JSON:API which scales infinitely compared to GraphQL.
@aimeos Sorry, just to clarify, this would be used for a custom admin panel. Not for the storefront API.
GraphQL could be quite good for this use case :)
Yes, for the admin backend we are already working on a GraphQL interface. We've already played around with graphql-php package (https://webonyx.github.io/graphql-php/) to test the best way for relations and filtering but we lack some time at the moment. If you want to help, you are heartly invited to join :-)
<?php
require_once( '../vendor/autoload.php' );
use GraphQL\GraphQL;
use GraphQL\Type\Schema;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\InputObjectField;
use GraphQL\Type\Definition\InputObjectType;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\ResolveInfo;
class Registry
{
private $types = [];
private $resolve = [];
private $args = [];
public function add( $name, $type, $args, $resolve ) : self
{
$this->resolve[$name] = $resolve;
$this->types[$name] = $type;
$this->args[$name] = $args;
return $this;
}
public function type( $name ) : ?Type
{
return $this->types[$name] ?? null;
}
public function args( $name ) : array
{
return $this->args[$name] ?? [];
}
public function resolve( $name ) : ?callable
{
return $this->resolve[$name] ?? null;
}
}
$registry = new Registry();
$types = $support = [];
$support['media'] = [
'type' => new ObjectType( [
'name' => 'media',
'fields' => function() use ( $registry ) {
return [
'id' => Type::string(),
'siteid' => Type::string(),
'domain' => Type::string(),
'type' => Type::string(),
'url' => Type::string(),
'preview' => Type::string(),
'previews' => Type::listOf( new ObjectType( [
'name' => 'previews',
'fields' => [
'width' => Type::int(),
'url' => Type::string()
],
'resolveField' => function( $entry, $args, $context, ResolveInfo $info ) {
switch( $info->fieldName ) {
case 'width': return key( $entry );
case 'url': return current( $entry );
}
return null;
}
] ) ),
'status' => Type::int(),
'ctime' => Type::string(),
'mtime' => Type::string(),
'editor' => Type::string(),
];
},
'resolveField' => function( $mediaItem, $args, $context, ResolveInfo $info ) {
// return $mediaItem->get( 'media.' . $info->fieldName );
return $mediaItem['media.' . $info->fieldName] ?? null;
}
] ),
'args' => [
'type' => Type::string(),
],
'resolve' => function( $listItem, $args, $context, ResolveInfo $info ) {
// return $listItem->getRefItem();
return $listItem['media'] ?? [];
}
];
$support['lists'] = [
'type' => Type::listOf( new ObjectType( [
'name' => 'lists',
'fields' => function() use ( $registry ) {
return [
'id' => Type::string(),
'siteid' => Type::string(),
'domain' => Type::string(),
'type' => Type::string(),
'refid' => Type::string(),
'datestart' => Type::string(),
'dateend' => Type::string(),
'status' => Type::int(),
'ctime' => Type::string(),
'mtime' => Type::string(),
'editor' => Type::string(),
'media' => [
'type' => $registry->type( 'media' ),
'args' => $registry->args( 'media' ),
'resolve' => $registry->resolve( 'media' ),
]
];
},
'resolveField' => function( $listItem, $args, $context, ResolveInfo $info ) {
$prefix = join( '.', array_slice( $info->path, -4, 2 ) );
// return $listItem->get( $prefix . '.' . $info->fieldName );
return $listItem[$prefix . '.' . $info->fieldName] ?? null;
}
] ) ),
'args' => [
'domain' => Type::string(),
'type' => Type::string(),
],
'resolve' => function( $item, $args, $context, ResolveInfo $info ) {
// return $item->getListItems()
return $item['lists'] ?? [];
}
];
$types['product'] = [
'type' => new ObjectType( [
'name' => 'product',
'fields' => function() use ( $registry ) {
return [
['name' => 'id', 'type' => Type::string(), 'description' => 'Unique ID'],
'siteid' => Type::string(),
'code' => Type::string(),
'label' => Type::string(),
'datestart' => Type::string(),
'dateend' => Type::string(),
'status' => Type::int(),
'ctime' => Type::string(),
'mtime' => Type::string(),
'editor' => Type::string(),
'rating' => Type::string(),
'ratings' => Type::int(),
'lists' => [
'type' => $registry->type( 'lists' ),
'args' => $registry->args( 'lists' ),
'resolve' => $registry->resolve( 'lists' )
]
];
},
'resolveField' => function( $productItem, $args, $context, ResolveInfo $info ) {
// return $productItem->get( $info->parentType->name . '.' . $info->fieldName );
return $productItem[$info->parentType->name . '.' . $info->fieldName] ?? null;
}
] ),
'args' => [
['name' => 'filter', 'type' => Type::string(), 'defaultValue' => '{}', 'description' => 'Filter description'],
['name' => 'include', 'type' => Type::string(), 'defaultValue' => '{}', 'description' => 'Include description'],
['name' => 'sort', 'type' => Type::listOf(Type::string()), 'defaultValue' => [], 'description' => 'Sort description'],
['name' => 'offset', 'type' => Type::int(), 'defaultValue' => 0, 'description' => 'Offset description'],
['name' => 'limit', 'type' => Type::int(), 'defaultValue' => 0, 'description' => 'Limit description'],
],
'resolve' => function( $root, $args, $context, ResolveInfo $info ) {
return [
'product.id' => '1',
'product.siteid' => '1.',
'product.code' => 'test',
'product.label' => 'Test product',
'product.datestart' => null,
'product.dateend' => null,
'product.status' => 0,
'product.ctime' => '2000-01-01 00:00:00',
'product.mtime' => '2000-01-01 00:00:00',
'product.editor' => 'aimeos',
'product.rating' => '5.00',
'product.ratings' => 1,
'lists' => [[
'product.lists.id' => '1',
'product.lists.siteid' => '1.',
'product.lists.domain' => 'media',
'product.lists.type' => 'default',
'product.lists.refid' => '123',
'product.lists.datestart' => null,
'product.lists.dateend' => null,
'product.lists.status' => 1,
'product.lists.ctime' => '2000-01-01 00:00:00',
'product.lists.mtime' => '2000-01-01 00:00:00',
'product.lists.editor' => 'aimeos',
'media' => [
'media.id' => '1',
'media.siteid' => '1.',
'media.domain' => 'media',
'media.type' => 'default',
'media.url' => 'path/to/image1.jpg',
'media.preview' => 'path/to/image2.jpg',
'media.previews' => [
[250 => 'path/to/image3.jpg'],
[500 => 'path/to/image4.jpg'],
],
'media.status' => 1,
'media.ctime' => '2000-01-01 00:00:00',
'media.mtime' => '2000-01-01 00:00:00',
'media.editor' => 'aimeos',
]
]]
];
}
];
foreach( $support as $name => $entry) {
$registry->add( $name, $entry['type'], $entry['args'] ?? [], $entry['resolve'] ?? null );
}
foreach( $types as $name => $entry) {
$registry->add( $name, $entry['type'], $entry['args'] ?? [], $entry['resolve'] ?? null );
}
$schema = new Schema([
'query' => new ObjectType( [
'name' => 'query',
'fields' => $types
] ),
]);
try
{
$rawInput = file_get_contents('php://input');
$input = json_decode($rawInput, true);
$query = $input['query'] ?? null;
$root = [];
$context = null;
$variableValues = $input['variables'] ?? null;
$operationName = $input['operationName'] ?? null;
$output = GraphQL::executeQuery( $schema, $query, $root, $context, $variableValues, $operationName )->toArray();
}
catch (\Exception $e)
{
$output = [
'errors' => [[
'message' => $e->getMessage()
]]
];
}
header('Content-Type: application/json');
echo json_encode($output);
A GraphQL API for administration is now included in Aimeos 2022.10.1+
Hi guys
Will the Laravel Aimeos package work with the lighthouse-php GraphQL package?
Thanks!