Currently I have such 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);
}
}
In query() function it creates QueryType instance. I added to QueryType constructor PersonTable model class so that it could query persons from database.
QueryType.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);
}
I have set up factories in 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);
},
),
);
}
}
I am doing by this example which does not have any framework:
https://github.com/webonyx/graphql-php/tree/master/examples/01-blog
So the question is - how do I create queryType instance with injected PersonTable instance? I should somehow get from the factory the PersonTable instance but I do not understand how.
Update:
I decided to try to inject QueryType into the controller. Created such function:
public function __construct(QueryType $queryType)
{
$this->queryType = $queryType;
}
Now module\Application\src\Module.php getServiceConfig looks like this:
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
),
);
}
But I get error:
Catchable fatal error: Argument 1 passed to Application\Controller\IndexController::__construct() must be an instance of Application\GraphQL\Type\QueryType, none given, called in E:\projektai\php projektai\htdocs\graphQL_zend_3\vendor\zendframework\zend-servicemanager\src\Factory\InvokableFactory.php on line 32 and defined in E:\projektai\php projektai\htdocs\graphQL_zend_3\module\Application\src\Controller\IndexController.p
How can none be given if I configured in that function?
If I could inject into the controller, then I plan to do like this:
$schema = new Schema([
//'query' => Types::query()
'query' => $this->queryType
]);
So I would not need to call query() function which return the QueryType instance anyway.
And then PersonTable would be automatically injected into QueryType class.
Update:
I had created the factory, similar as in the asnswer:
class QueryTypeFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return new QueryType($container->get(PersonTable::class));
}
}
In the IndexController I have constructor:
public function __construct(QueryType $queryType)
{
$this->queryType = $queryType;
}
In the Module.php I use this factory:
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
),
);
}
It simply does not work, I get error:
Catchable fatal error: Argument 1 passed to Application\Controller\IndexController::__construct() must be an instance of Application\GraphQL\Type\QueryType, none given, called in E:\projektai\php projektai\htdocs\graphQL_zend_3\vendor\zendframework\zend-servicemanager\src\Factory\InvokableFactory.php on line 32 and defined in E:\projektai\php projektai\htdocs\graphQL_zend_3\module\Application\src\Controller\IndexController.php on line
I also tried this way:
$queryTypeFactory = new QueryTypeFactory();
// GraphQL schema to be passed to query executor:
$schema = new Schema([
//'query' => Types::query()
//'query' => $this->queryType
// 'query' => $queryType
'query' => $queryTypeFactory()
]);
But the $queryTypeFactory() needs parameter $container. Which is not what I want, I guess. I should be able to create an instance without passing parameters.
I hope it is ok to use QueryType::class in the factories array as key. It will create with full name space which is set:
use Application\GraphQL\Type\QueryType;
And in index controller I also call that use statement.
<?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);
}
}
In the code above we have the PurchaseManagerFactory class which implements the Zend\ServiceManager\Factory\FactoryInterface interface. The factory class has the __invoke() method whose goal is to instantiate the object. This method has the $container argument which is the service manager. You can use $container to retrieve services from service manager and pass them to the constructor method of the service being instantiated.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With