Here is my index file with url paths:
<?php
require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/../app/Config/bootstrap.php';
use FastRouteRouteCollector;
use FastRouteDispatcher;
use AppControllerGraphQL;
use DoctrineORMEntityManagerInterface;
// Create an instance of the GraphQL controller with the entity manager
$graphQLController = new GraphQL($entityManager);
$dispatcher = FastRoutesimpleDispatcher(function(FastRouteRouteCollector $r) use ($graphQLController) {
$r->post('/category/{category_name}', [$graphQLController, 'mainPage']);
});
$routeInfo = $dispatcher->dispatch(
$_SERVER['REQUEST_METHOD'],
$_SERVER['REQUEST_URI']
);
switch ($routeInfo[0]) {
case FastRouteDispatcher::NOT_FOUND:
// ... 404 Not Found
http_response_code(404);
echo '404 Not Found';
break;
case FastRouteDispatcher::METHOD_NOT_ALLOWED:
$allowedMethods = $routeInfo[1];
// ... 405 Method Not Allowed
http_response_code(405);
echo '405 Method Not Allowed';
break;
case FastRouteDispatcher::FOUND:
$handler = $routeInfo[1];
$vars = $routeInfo[2];
echo call_user_func($handler, $vars);
break;
}
Here is my controller
<?php
namespace AppController;
use AppEntityPrice;
use AppEntityCurrency;
use AppModelsCategory;
use AppModelsProduct;
use AppEntityItem;
use AppModelsAttribute;
use GraphQLGraphQL as GraphQLBase;
use GraphQLTypeDefinitionObjectType;
use GraphQLTypeDefinitionType;
use GraphQLTypeSchema;
use GraphQLTypeSchemaConfig;
use RuntimeException;
use Throwable;
use DoctrineORMEntityManagerInterface;
class GraphQL {
private $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
public function mainPage() {
try {
$itemType = new ObjectType([
'name' => 'Item',
'fields' => [
'item_id' => Type::int(),
'displayValue' => Type::string(),
'value' => Type::string(),
'id' => Type::string(),
]
]);
$attributeType = new ObjectType([
'name' => 'Attribute',
'fields' => [
'attribute_id' => Type::int(),
'id' => Type::string(),
'name' => Type::string(),
'type' => Type::string(),
'items' => [
'type' => Type::listOf($itemType),
'resolve' => function ($attribute) {
$items = $this->entityManager->getRepository(Item::class)
->findBy(['attribute' => $attribute['attribute_id']]);
return array_map(function ($item) {
return [
'item_id' => $item->getItem_id(),
'displayValue' => $item->getDisplayValue(),
'value' => $item->getValue(),
'id' => $item->getId(),
];
}, $items);
}
]
]
]);
$currencyType = new ObjectType([
'name' => 'Currency',
'fields' => [
'currency_id' => Type::int(),
'label' => Type::string(),
'symbol' => Type::string(),
]
]);
$priceType = new ObjectType([
'name' => 'Price',
'fields' => [
'price_id' => Type::int(),
'amount' => Type::float(),
'currency' => $currencyType,
],
]);
$productType = new ObjectType([
'name' => 'Product',
'fields' => [
'product_id' => Type::int(),
'id' => Type::string(),
'name' => Type::string(),
'in_stock' => Type::boolean(),
'gallery' => Type::listOf(Type::string()),
'description' => Type::string(),
'brand' => Type::string(),
'attributes' => [
'type' => Type::listOf($attributeType),
'resolve' => function ($product) {
$attributeResolver = new AttributeResolver($this->entityManager);
return $attributeResolver->resolveAttributes($product);
}
],
'prod_prices' =>[
'type' => Type::listOf($priceType),
'resolve' => function ($product){
$prices = $this->entityManager->getRepository(Price::class)
->findBy(['product' => $product['product_id']]);
return array_map(function ($price) {
return [
'price_id' => $price->getPriceId(),
'amount' => $price->getAmount(),
$priceCurrency = $price->getCurrency(),
'currency' => [
'currency_id' => $priceCurrency->getCurrencyId(),
'label' => $priceCurrency->getLabel(),
'symbol' => $priceCurrency->getSymbol(),
],
];
}, $prices);
}
]
],
]);
$categoryType = new ObjectType([
'name' => 'Category',
'fields' => [
'category_id' => Type::int(),
'category_name' => Type::string(),
'products' => [
'type' => Type::listOf($productType),
'resolve' => function ($category) {
// Fetch products for the current category
$products = $this->entityManager->getRepository(Product::class)
->findBy(['category' => $category['category_id']]);
//map products to the category
return array_map(function ($product) {
return [
'product_id' => $product->getProductId(),
'id' => $product->getId(),
'name' => $product->getName(),
'in_stock' => $product->getIn_stock(),
'gallery' => $product->getGallery(),
'description' => $product->getDescription(),
'brand' => $product->getBrand(),
'attributes' => $product->getAttributes(),
'prices' => $product->getprod_prices(),
];
}, $products);
},
],
],
]);
//I want to make a query that will return all three category's and provided categories products
$queryType = new ObjectType([
'name' => 'Query',
'fields' => [
'categories' => [
'type' => Type::listOf($categoryType),
'args' => [
'category_name' => Type::string(),
],
'resolve' => function ($root, $args) {
$categoryName = $args['category_name'] ?? null;
// Fetch all categories
$categories = $this->entityManager->getRepository(Category::class)->findAll();
$result = array_map(function ($category) use ($categoryName) {
$result = [
'category_id' => $category->getCategoryId(),
'category_name' => $category->getCategory(),
];
// Check if the category_name matches the current category's name
if ($categoryName === $category->getCategory()) {
try{
$result['products'] = Array($category->getProducts());
}catch (Throwable $e) {
$output = [
'error' => [
'message' => $e->getMessage(),
],
];
}
} else {
// Exclude products for categories other than $categoryName
$result['products'] = []; // or null, depending on how you want to handle this case
}
return $result;
}, $categories);
return $result;
}
],
],
]);
$schema = new Schema(
(new SchemaConfig())
->setQuery($queryType)
);
$rawInput = file_get_contents('php://input');
if ($rawInput === false) {
throw new RuntimeException('Failed to get php://input');
}
if (empty($rawInput)) {
throw new RuntimeException('Empty query input');
}
$input = json_decode($rawInput, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new RuntimeException('Invalid JSON input: ' . json_last_error_msg());
}
$query = $input['query'] ?? null;
if ($query === null) {
throw new RuntimeException('Query not provided');
}
$variableValues = $input['variables'] ?? null;
$result = GraphQLBase::executeQuery($schema, $query, null, null, $variableValues);
$output = $result->toArray();
} catch (Throwable $e) {
$output = [
'error' => [
'message' => $e->getMessage(),
],
];
}
header('Content-Type: application/json; charset=UTF-8');
echo json_encode($output);
}
}
Currently I can get all the categories and their products, however I want all the categories and only products for the provided category in the arguments.
Curl post request to get all the categories and products.
curl -X POST http://localhost:8000/category/clothes -H "Content-Type: application/json" -d '{"query": "query { categories(category_name: "clothes") { category_id category_name products { product_id } } }"}'
Do I need to use the $root argument in my resolver function to do something like that. Because my current idea is just to look with a if statement if there is the correct category name and provide products but leave a empty array for other category products.
Any tips or ideas would be nice :).