我制作了一个 graphql 控制器,它可以从 Dom 中解析有关类别的信息。当我在终端输入以下命令时,问题就开始了:
curl -X POST http://localhost:8000/graphql -H "Content-Type: application/json" -d '{"query": "{ category(id: 1) { category_id category_name } }"}'
类别类
<?php
namespace App\Models;
use App\Entity\TechCategory;
use App\Entity\ClothCategory;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
#[ORM\Entity]
#[ORM\Table(name: 'category')]
#[ORM\InheritanceType("SINGLE_TABLE")]
#[ORM\DiscriminatorColumn(name: 'discr', type: 'string')]
#[ORM\DiscriminatorMap(['tech' => TechCategory::class, 'cloth' => ClothCategory::class])]
class Category
{
#[ORM\Id]
#[ORM\Column(type: 'integer')]
#[ORM\GeneratedValue]
protected $category_id;
#[ORM\Column(type: 'string')]
protected $category_name;
//There can be many products to a single category
#[ORM\OneToMany(targetEntity: "Product", mappedBy: "category")]
protected Collection $products;
public function __construct()
{
$this->products = new ArrayCollection();
}
// Getters and setters...
public function getCategoryId(): int
{
return $this->category_id;
}
public function getCategory(): string
{
return $this->category_name;
}
public function setCategory(string $category_name): void
{
$this->category_name = $category_name;
}
public function getProducts(): Collection
{
return $this->products;
}
public function addProduct(Product $product): void
{
if (!$this->products->contains($product)) {
$this->products[] = $product;
$product->setCategory($this);
}
}
public function removeProduct(Product $product): void
{
if ($this->products->contains($product)) {
$this->products->removeElement($product);
if ($product->getCategory() === $this) {
$product->getCategory(null);
}
}
}
}
Graphql 控制器
<?php
namespace App\Controller;
use App\Models\Category;
use GraphQL\GraphQL as GraphQLBase;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Schema;
use GraphQL\Type\SchemaConfig;
use RuntimeException;
use Throwable;
use Doctrine\ORM\EntityManagerInterface;
class GraphQL {
private $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
public function handle() {
try {
//Category: category_id, category_name, products
$categoryType = new ObjectType([
'name' => 'Category',
'fields' => [
'category_id' => Type::int(),
'category_name' => Type::string(),
]
]);
$queryType = new ObjectType([
'name' => 'Query',
'fields' => [
'category' => [
'type' => $categoryType,
'args' => [
'id' => ['type' => Type::int()],
],
'resolve' => function ($rootValue, array $args) {
$categoryId = $args['id'];
return $this->entityManager->getRepository(Category::class)->find($categoryId);
},
],
],
]);
$schema = new Schema(
(new SchemaConfig())
->setQuery($queryType)
// ->setMutation($mutationType)
);
$rawInput = file_get_contents('php://input');
if ($rawInput === false) {
throw new RuntimeException('Failed to get php://input');
}
$input = json_decode($rawInput, true);
$query = $input['query'];
$variableValues = $input['variables'] ?? null;
// $rootValue = ['prefix' => 'You said: '];
$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');
return json_encode($output);
}
}
索引.php
<?php
require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/../app/Config/bootstrap.php';
use FastRoute\RouteCollector;
use FastRoute\Dispatcher;
use App\Controller\GraphQL;
use Doctrine\ORM\EntityManagerInterface;
$graphQLController = new GraphQL($entityManager);
$dispatcher = FastRoute\simpleDispatcher(function(FastRoute\RouteCollector $r) use ($graphQLController) {
$r->post('/graphql', [$graphQLController, 'handle']);
});
$routeInfo = $dispatcher->dispatch(
$_SERVER['REQUEST_METHOD'],
$_SERVER['REQUEST_URI']
);
switch ($routeInfo[0]) {
case FastRoute\Dispatcher::NOT_FOUND:
// ... 404 Not Found
http_response_code(404);
echo '404 Not Found';
break;
case FastRoute\Dispatcher::METHOD_NOT_ALLOWED:
$allowedMethods = $routeInfo[1];
// ... 405 Method Not Allowed
http_response_code(405);
echo '405 Method Not Allowed';
break;
case FastRoute\Dispatcher::FOUND:
$handler = $routeInfo[1];
$vars = $routeInfo[2];
echo call_user_func($handler, $vars);
break;
}
运行curl命令时得到的输出是
{"data":{"category":{"category_id":null,"category_name":null}}}
想法
Doctrine 设置正确,我可以通过实体管理器列出 mysql 数据库中的行,但是当我尝试查询它们时,问题就开始了。我不知道是因为我的类别类中有产品数组还是因为我的类别类有子类。
任何帮助将不胜感激!
我猜 graphql 不知道如何映射返回的 Category 对象值。必须更改查询类型。
$queryType = new ObjectType([
'name' => 'Query',
'fields' => [
'category' => [
'type' => $categoryType,
'args' => [
'id' => ['type' => Type::int()],
],
'resolve' => function ($rootValue, array $args) {
$categoryId = $args['id'];
$category = $this->entityManager->getRepository(Category::class)->find($categoryId);
if (!$category) {
throw new \RuntimeException("Category not found with ID: $categoryId");
}
return [
'category_id' => $category->getCategoryId(),
'category_name' => $category->getCategory(),
];
},
],
],
]);