Updated blog example: demonstrated and commented inheritance vs composition options; added describing comments

This commit is contained in:
vladar 2016-10-24 17:07:52 +07:00
parent 19436c326d
commit 29670b378b
16 changed files with 39 additions and 60 deletions

View File

@ -7,7 +7,7 @@ use GraphQL\Utils;
/** /**
* Class AppContext * Class AppContext
* Instance available in all GraphQL resolvers * Instance available in all GraphQL resolvers as 3rd argument
* *
* @package GraphQL\Examples\Social * @package GraphQL\Examples\Social
*/ */

View File

@ -4,8 +4,11 @@ namespace GraphQL\Examples\Blog\Type;
use GraphQL\Type\Definition\Type; use GraphQL\Type\Definition\Type;
use GraphQL\Type\DefinitionContainer; use GraphQL\Type\DefinitionContainer;
class BaseType implements DefinitionContainer abstract class BaseType implements DefinitionContainer
{ {
// Base class to reduce boilerplate for those who prefer own clean hierarchy of classes
// (and avoids extending GraphQL classes directly)
/** /**
* @var Type * @var Type
*/ */

View File

@ -11,6 +11,7 @@ class CommentType extends BaseType
{ {
public function __construct(TypeSystem $types) public function __construct(TypeSystem $types)
{ {
// Option #1: using composition over inheritance to define type, see ImageType for inheritance example
$this->definition = new ObjectType([ $this->definition = new ObjectType([
'name' => 'Comment', 'name' => 'Comment',
'fields' => function() use ($types) { 'fields' => function() use ($types) {
@ -18,6 +19,7 @@ class CommentType extends BaseType
'id' => $types->id(), 'id' => $types->id(),
'author' => $types->user(), 'author' => $types->user(),
'parent' => $types->comment(), 'parent' => $types->comment(),
'isAnonymous' => $types->boolean(),
'replies' => [ 'replies' => [
'type' => $types->listOf($types->comment()), 'type' => $types->listOf($types->comment()),
'args' => [ 'args' => [
@ -45,6 +47,9 @@ class CommentType extends BaseType
public function author(Comment $comment, $args, AppContext $context) public function author(Comment $comment, $args, AppContext $context)
{ {
if ($comment->isAnonymous) {
return null;
}
return $context->dataSource->findUser($comment->authorId); return $context->dataSource->findUser($comment->authorId);
} }

View File

@ -11,6 +11,7 @@ class ContentFormatEnum extends BaseType
public function __construct() public function __construct()
{ {
// Option #1: Define type using composition over inheritance, see ImageSizeEnumType for inheritance option
$this->definition = new EnumType([ $this->definition = new EnumType([
'name' => 'ContentFormatEnum', 'name' => 'ContentFormatEnum',
'values' => [self::FORMAT_TEXT, self::FORMAT_HTML] 'values' => [self::FORMAT_TEXT, self::FORMAT_HTML]

View File

@ -2,24 +2,23 @@
namespace GraphQL\Examples\Blog\Type\Enum; namespace GraphQL\Examples\Blog\Type\Enum;
use GraphQL\Examples\Blog\Data\Image; use GraphQL\Examples\Blog\Data\Image;
use GraphQL\Examples\Blog\Type\BaseType;
use GraphQL\Type\Definition\EnumType; use GraphQL\Type\Definition\EnumType;
class ImageSizeEnumType extends BaseType class ImageSizeEnumType extends EnumType
{ {
/**
* ImageSizeEnumType constructor.
*/
public function __construct() public function __construct()
{ {
$this->definition = new EnumType([ // Option #2: Define enum type using inheritance
'name' => 'ImageSizeEnum', $config = [
// Note: 'name' option is not needed in this form - it will be inferred from className
'values' => [ 'values' => [
'ICON' => Image::SIZE_ICON, 'ICON' => Image::SIZE_ICON,
'SMALL' => Image::SIZE_SMALL, 'SMALL' => Image::SIZE_SMALL,
'MEDIUM' => Image::SIZE_MEDIUM, 'MEDIUM' => Image::SIZE_MEDIUM,
'ORIGINAL' => Image::SIZE_ORIGINAL 'ORIGINAL' => Image::SIZE_ORIGINAL
] ]
]); ];
parent::__construct($config);
} }
} }

View File

@ -10,6 +10,9 @@ class HtmlField
{ {
$objectKey = $objectKey ?: $name; $objectKey = $objectKey ?: $name;
// Demonstrates how to organize re-usable fields
// Usual example: when the same field with same args shows up in different types
// (for example when it is a part of some interface)
return [ return [
'name' => $name, 'name' => $name,
'type' => $types->string(), 'type' => $types->string(),

View File

@ -1,31 +0,0 @@
<?php
namespace GraphQL\Examples\Blog\Type;
use GraphQL\Examples\Blog\Type\Enum\ContentFormatEnum;
use GraphQL\Examples\Blog\TypeSystem;
/**
* Class Field
* @package GraphQL\Examples\Blog\Type
*/
class FieldDefinitions
{
private $types;
public function __construct(TypeSystem $types)
{
$this->types = $types;
}
private $htmlField;
public function htmlField($name, $objectKey = null)
{
$objectKey = $objectKey ?: $name;
return $this->htmlField ?: $this->htmlField = [
'name' => $name,
];
}
}

View File

@ -7,11 +7,12 @@ use GraphQL\Examples\Blog\TypeSystem;
use GraphQL\Type\Definition\EnumType; use GraphQL\Type\Definition\EnumType;
use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\ObjectType;
class ImageType extends BaseType class ImageType extends ObjectType
{ {
public function __construct(TypeSystem $types) public function __construct(TypeSystem $types)
{ {
$this->definition = new ObjectType([ // Option #2: define type using inheritance, see any other object type for compositional example
$config = [
'name' => 'ImageType', 'name' => 'ImageType',
'fields' => [ 'fields' => [
'id' => $types->id(), 'id' => $types->id(),
@ -43,7 +44,9 @@ class ImageType extends BaseType
} }
] ]
] ]
]); ];
parent::__construct($config);
} }
public function resolveUrl(Image $value, $args, AppContext $context) public function resolveUrl(Image $value, $args, AppContext $context)

View File

@ -11,6 +11,7 @@ class MentionType extends BaseType
{ {
public function __construct(TypeSystem $types) public function __construct(TypeSystem $types)
{ {
// Option #1: using composition over inheritance to define type, see ImageType for inheritance example
$this->definition = new UnionType([ $this->definition = new UnionType([
'name' => 'Mention', 'name' => 'Mention',
'types' => function() use ($types) { 'types' => function() use ($types) {

View File

@ -9,12 +9,9 @@ use GraphQL\Type\Definition\InterfaceType;
class NodeType extends BaseType class NodeType extends BaseType
{ {
/**
* NodeType constructor.
* @param TypeSystem $types
*/
public function __construct(TypeSystem $types) public function __construct(TypeSystem $types)
{ {
// Option #1: using composition over inheritance to define type, see ImageType for inheritance example
$this->definition = new InterfaceType([ $this->definition = new InterfaceType([
'name' => 'Node', 'name' => 'Node',
'fields' => [ 'fields' => [

View File

@ -11,6 +11,7 @@ class QueryType extends BaseType
{ {
public function __construct(TypeSystem $types) public function __construct(TypeSystem $types)
{ {
// Option #1: using composition over inheritance to define type, see ImageType for inheritance example
$this->definition = new ObjectType([ $this->definition = new ObjectType([
'name' => 'Query', 'name' => 'Query',
'fields' => [ 'fields' => [

View File

@ -10,6 +10,7 @@ class EmailType extends BaseType
{ {
public function __construct() public function __construct()
{ {
// Option #1: define scalar types using composition (see UrlType fo option #2 using inheritance)
$this->definition = new CustomScalarType([ $this->definition = new CustomScalarType([
'name' => 'Email', 'name' => 'Email',
'serialize' => [$this, 'serialize'], 'serialize' => [$this, 'serialize'],

View File

@ -5,14 +5,9 @@ use GraphQL\Language\AST\StringValue;
use GraphQL\Type\Definition\ScalarType; use GraphQL\Type\Definition\ScalarType;
use GraphQL\Utils; use GraphQL\Utils;
/** class UrlType extends ScalarType
* Class UrlTypeDefinition
*
* @package GraphQL\Examples\Blog\Type\Scalar
*/
class UrlTypeDefinition extends ScalarType
{ {
public $name = 'Url'; // Option #2: Displays scalar type defined using inheritance. See EmailType for definition via composition
/** /**
* Serializes an internal value to include in a response. * Serializes an internal value to include in a response.

View File

@ -23,6 +23,7 @@ class StoryType extends BaseType
public function __construct(TypeSystem $types) public function __construct(TypeSystem $types)
{ {
// Option #1: using composition over inheritance to define type, see ImageType for inheritance example
$this->definition = new ObjectType([ $this->definition = new ObjectType([
'name' => 'Story', 'name' => 'Story',
'fields' => function() use ($types) { 'fields' => function() use ($types) {

View File

@ -11,6 +11,7 @@ class UserType extends BaseType
{ {
public function __construct(TypeSystem $types) public function __construct(TypeSystem $types)
{ {
// Option #1: using composition over inheritance to define type, see ImageType for inheritance example
$this->definition = new ObjectType([ $this->definition = new ObjectType([
'name' => 'User', 'name' => 'User',
'fields' => function() use ($types) { 'fields' => function() use ($types) {

View File

@ -5,13 +5,12 @@ use GraphQL\Examples\Blog\Type\CommentType;
use GraphQL\Examples\Blog\Type\Enum\ContentFormatEnum; use GraphQL\Examples\Blog\Type\Enum\ContentFormatEnum;
use GraphQL\Examples\Blog\Type\Enum\ImageSizeEnumType; use GraphQL\Examples\Blog\Type\Enum\ImageSizeEnumType;
use GraphQL\Examples\Blog\Type\Field\HtmlField; use GraphQL\Examples\Blog\Type\Field\HtmlField;
use GraphQL\Examples\Blog\Type\FieldDefinitions;
use GraphQL\Examples\Blog\Type\MentionType; use GraphQL\Examples\Blog\Type\MentionType;
use GraphQL\Examples\Blog\Type\NodeType; use GraphQL\Examples\Blog\Type\NodeType;
use GraphQL\Examples\Blog\Type\QueryType; use GraphQL\Examples\Blog\Type\QueryType;
use GraphQL\Examples\Blog\Type\Scalar\EmailType; use GraphQL\Examples\Blog\Type\Scalar\EmailType;
use GraphQL\Examples\Blog\Type\StoryType; use GraphQL\Examples\Blog\Type\StoryType;
use GraphQL\Examples\Blog\Type\Scalar\UrlTypeDefinition; use GraphQL\Examples\Blog\Type\Scalar\UrlType;
use GraphQL\Examples\Blog\Type\UserType; use GraphQL\Examples\Blog\Type\UserType;
use GraphQL\Examples\Blog\Type\ImageType; use GraphQL\Examples\Blog\Type\ImageType;
use GraphQL\Type\Definition\ListOfType; use GraphQL\Type\Definition\ListOfType;
@ -129,15 +128,15 @@ class TypeSystem
public function email() public function email()
{ {
return $this->emailType ?: ($this->emailType = new EmailType); return $this->emailType ?: ($this->emailType = new EmailType());
} }
/** /**
* @return UrlTypeDefinition * @return UrlType
*/ */
public function url() public function url()
{ {
return $this->urlType ?: ($this->urlType = new UrlTypeDefinition); return $this->urlType ?: ($this->urlType = new UrlType());
} }
/** /**