5

目前我有这样的Types.php:

namespace Application\GraphQL;

use Application\GraphQL\Type\NodeType;

use Application\GraphQL\Type\QueryType;
use GraphQL\Type\Definition\NonNull;
use GraphQL\Type\Definition\Type;
use Application\GraphQL\Type\PersonType;

/**
 * Class Types
 *
 * Acts as a registry and factory for your types.
 *
 * As simplistic as possible for the sake of clarity of this example.
 * Your own may be more dynamic (or even code-generated).
 *
 * @package GraphQL\Examples\Blog
 */
class Types
{

    private static $query;
    private static $person;
    private static $node;


    public static function person()
    {
        return self::$person ?: (self::$person = new PersonType());
    }

    /**
     * @return QueryType
     */
    public static function query()
    {
        return self::$query ?: (self::$query = new QueryType());
    }

    /**
     * @return NodeType
     */
    public static function node()
    {
        return self::$node ?: (self::$node = new NodeType());
    }

    /**
     * @return \GraphQL\Type\Definition\IDType
     */
    public static function id()
    {
        return Type::id();
    }

    /**
     * @return \GraphQL\Type\Definition\StringType
     */
    public static function string()
    {
        return Type::string();
    }

    /**
     * @param Type $type
     * @return NonNull
     */
    public static function nonNull($type)
    {
        return new NonNull($type);
    }
}

在 query() 函数中,它创建 QueryType 实例。我添加到 QueryType 构造函数 PersonTable 模型类,以便它可以从数据库中查询人员。

查询类型.php

public function __construct(PersonTable $table)
    {
        $config = [
            'name' => 'Query',
            'fields' => [
                'person' => [
                    'type' => Types::person(),
                    'description' => 'Returns person by id',
                    'args' => [
                        'id' => Types::nonNull(Types::id())
                    ]
                ],
                'hello' => Type::string()
            ],
            'resolveField' => function($val, $args, $context, ResolveInfo $info) {
                return $this->{$info->fieldName}($val, $args, $context, $info);
            }
        ];

        $this->table = $table;
        parent::__construct($config);
    }

我在 module\Application\src\Module.php 中设置了工厂:

/**
 * @link      http://github.com/zendframework/ZendSkeletonApplication for the canonical source repository
 * @copyright Copyright (c) 2005-2016 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Application;

use Application\Model\PersonTable;

use Application\Model\Person;

use Zend\Db\ResultSet\ResultSet;
use Zend\Db\TableGateway\TableGateway;

class Module
{
    const VERSION = '3.0.2dev';

    public function getConfig()
    {
        return include __DIR__ . '/../config/module.config.php';
    }

    // Add this method:
    public function getServiceConfig()
    {
        return array(
            'factories' => array(
                'Application\Model\PersonTable' =>  function($sm) {
                    $tableGateway = $sm->get('PersonTableGateway');
                    $table = new PersonTable($tableGateway);
                    return $table;
                },
                'PersonTableGateway' => function ($sm) {
                    $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
                    $resultSetPrototype = new ResultSet();
                    $resultSetPrototype->setArrayObjectPrototype(new Person());
                    return new TableGateway('album', $dbAdapter, null, $resultSetPrototype);
                },
            ),
        );
    }
}

我正在做这个没有任何框架的例子:

https://github.com/webonyx/graphql-php/tree/master/examples/01-blog

所以问题是 - 如何使用注入的 PersonTable 实例创建 queryType 实例?我应该以某种方式从工厂获取 PersonTable 实例,但我不明白如何。

更新:

我决定尝试将 QueryType 注入控制器。创建了这样的功能:

public function __construct(QueryType $queryType)
    {
        $this->queryType = $queryType;
    }

现在 module\Application\src\Module.php getServiceConfig 看起来像这样:

 public function getServiceConfig()
    {
        return array(
            'factories' => array(
                'Application\Model\PersonTable' =>  function($sm) {
                    $tableGateway = $sm->get('PersonTableGateway');
                    $table = new PersonTable($tableGateway);
                    return $table;
                },
                'PersonTableGateway' => function ($sm) {
                    $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
                    $resultSetPrototype = new ResultSet();
                    $resultSetPrototype->setArrayObjectPrototype(new Person());
                    return new TableGateway('album', $dbAdapter, null, $resultSetPrototype);
                },
                QueryType::class => function ($sm) {
                    return new QueryType($sm->get(PersonTable::class));
                }
                // when putting in namespace does not find??????????
                //QueryType::class => Application\GraphQL\Type\Factories\QueryTypeFactory::class
                //QueryType::class => \QueryTypeFactory::class

            ),
        );
    }

但我得到错误:

可捕获的致命错误:传递给 Application\Controller\IndexController::__construct() 的参数 1 必须是 Application\GraphQL\Type\QueryType 的实例,没有给出,在 E:\projektai\php projektai\htdocs\graphQL_zend_3\vendor\ 中调用zendframework\zend-servicemanager\src\Factory\InvokableFactory.php 在第 32 行并在 E:\projektai\php projektai\htdocs\graphQL_zend_3\module\Application\src\Controller\IndexController.p 中定义

如果我在该功能中配置,怎么能不给出?

如果我可以注入控制器,那么我打算这样做:

 $schema = new Schema([
                //'query' => Types::query()
                'query' => $this->queryType
            ]);

所以我不需要调用返回 QueryType 实例的 query() 函数。

然后将 PersonTable 自动注入到 QueryType 类中。

更新:

我创建了工厂,类似于答案:

class QueryTypeFactory implements FactoryInterface
{

    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        return new QueryType($container->get(PersonTable::class));
    }

}

在 IndexController 我有构造函数:

public function __construct(QueryType $queryType)
    {
        $this->queryType = $queryType;
    }

在 Module.php 我使用这个工厂:

public function getServiceConfig()
    {
        return array(
            'factories' => array(
                'Application\Model\PersonTable' =>  function($sm) {
                    $tableGateway = $sm->get('PersonTableGateway');
                    $table = new PersonTable($tableGateway);
                    return $table;
                },
                'PersonTableGateway' => function ($sm) {
                    $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
                    $resultSetPrototype = new ResultSet();
                    $resultSetPrototype->setArrayObjectPrototype(new Person());
                    return new TableGateway('album', $dbAdapter, null, $resultSetPrototype);
                },
//                QueryType::class => function ($sm) {
//                    //return new QueryType($sm->get(PersonTable::class));
//
//                }

                //QueryType::class => Application\GraphQL\Type\Factories\QueryTypeFactory::class
                //QueryType::class => \QueryTypeFactory::class
                QueryType::class => QueryTypeFactory::class

            ),
        );
    }

它根本不起作用,我收到错误:

可捕获的致命错误:传递给 Application\Controller\IndexController::__construct() 的参数 1 必须是 Application\GraphQL\Type\QueryType 的实例,没有给出,在 E:\projektai\php projektai\htdocs\graphQL_zend_3\vendor\ 中调用zendframework\zend-servicemanager\src\Factory\InvokableFactory.php 在第 32 行并在 E:\projektai\php projektai\htdocs\graphQL_zend_3\module\Application\src\Controller\IndexController.php 在线定义

我也尝试过这种方式:

$queryTypeFactory = new QueryTypeFactory();

            // GraphQL schema to be passed to query executor:
            $schema = new Schema([
                //'query' => Types::query()
                //'query' => $this->queryType
              //  'query' => $queryType
                'query' => $queryTypeFactory()
            ]);

但是 $queryTypeFactory() 需要参数 $container。这不是我想要的,我猜。我应该能够在不传递参数的情况下创建一个实例。

我希望可以在工厂数组中使用 QueryType::class 作为键。它将使用设置的全名空间创建:

use Application\GraphQL\Type\QueryType;

在索引控制器中,我也称之为 use 语句。

4

1 回答 1

2
<?php
namespace Application\Service\Factory;

use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
use Application\Service\CurrencyConverter;
use Application\Service\PurchaseManager;

/**
 * This is the factory for PurchaseManager service. Its purpose is to instantiate the 
 * service and inject its dependencies.
 */
class PurchaseManagerFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, 
                $requestedName, array $options = null)
    {
        // Get CurrencyConverter service from the service manager.
        $currencyConverter = $container->get(CurrencyConverter::class);

        // Instantiate the service and inject dependencies.
        return new PurchaseManager($currencyConverter);
    }
}

在上面的代码中,我们有实现 Zend\ServiceManager\Factory\FactoryInterface 接口的 PurchaseManagerFactory 类。工厂类有 __invoke() 方法,其目标是实例化对象。此方法具有 $container 参数,即服务管理器。您可以使用 $container 从服务管理器中检索服务并将它们传递给正在实例化的服务的构造函数方法。

于 2017-02-10T05:39:41.373 回答