From 29670b378bda350a417e08a1509b5df322bfb353 Mon Sep 17 00:00:00 2001 From: vladar Date: Mon, 24 Oct 2016 17:07:52 +0700 Subject: [PATCH] Updated blog example: demonstrated and commented inheritance vs composition options; added describing comments --- examples/01-blog/Blog/AppContext.php | 2 +- examples/01-blog/Blog/Type/BaseType.php | 5 ++- examples/01-blog/Blog/Type/CommentType.php | 5 +++ .../Blog/Type/Enum/ContentFormatEnum.php | 1 + .../Blog/Type/Enum/ImageSizeEnumType.php | 15 +++++---- .../01-blog/Blog/Type/Field/HtmlField.php | 3 ++ .../01-blog/Blog/Type/FieldDefinitions.php | 31 ------------------- examples/01-blog/Blog/Type/ImageType.php | 9 ++++-- examples/01-blog/Blog/Type/MentionType.php | 1 + examples/01-blog/Blog/Type/NodeType.php | 5 +-- examples/01-blog/Blog/Type/QueryType.php | 1 + .../01-blog/Blog/Type/Scalar/EmailType.php | 1 + .../{UrlTypeDefinition.php => UrlType.php} | 9 ++---- examples/01-blog/Blog/Type/StoryType.php | 1 + examples/01-blog/Blog/Type/UserType.php | 1 + examples/01-blog/Blog/TypeSystem.php | 9 +++--- 16 files changed, 39 insertions(+), 60 deletions(-) delete mode 100644 examples/01-blog/Blog/Type/FieldDefinitions.php rename examples/01-blog/Blog/Type/Scalar/{UrlTypeDefinition.php => UrlType.php} (88%) diff --git a/examples/01-blog/Blog/AppContext.php b/examples/01-blog/Blog/AppContext.php index 3c43858..2113b68 100644 --- a/examples/01-blog/Blog/AppContext.php +++ b/examples/01-blog/Blog/AppContext.php @@ -7,7 +7,7 @@ use GraphQL\Utils; /** * Class AppContext - * Instance available in all GraphQL resolvers + * Instance available in all GraphQL resolvers as 3rd argument * * @package GraphQL\Examples\Social */ diff --git a/examples/01-blog/Blog/Type/BaseType.php b/examples/01-blog/Blog/Type/BaseType.php index e598ed1..af14eea 100644 --- a/examples/01-blog/Blog/Type/BaseType.php +++ b/examples/01-blog/Blog/Type/BaseType.php @@ -4,8 +4,11 @@ namespace GraphQL\Examples\Blog\Type; use GraphQL\Type\Definition\Type; 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 */ diff --git a/examples/01-blog/Blog/Type/CommentType.php b/examples/01-blog/Blog/Type/CommentType.php index a432fdc..57a7658 100644 --- a/examples/01-blog/Blog/Type/CommentType.php +++ b/examples/01-blog/Blog/Type/CommentType.php @@ -11,6 +11,7 @@ class CommentType extends BaseType { public function __construct(TypeSystem $types) { + // Option #1: using composition over inheritance to define type, see ImageType for inheritance example $this->definition = new ObjectType([ 'name' => 'Comment', 'fields' => function() use ($types) { @@ -18,6 +19,7 @@ class CommentType extends BaseType 'id' => $types->id(), 'author' => $types->user(), 'parent' => $types->comment(), + 'isAnonymous' => $types->boolean(), 'replies' => [ 'type' => $types->listOf($types->comment()), 'args' => [ @@ -45,6 +47,9 @@ class CommentType extends BaseType public function author(Comment $comment, $args, AppContext $context) { + if ($comment->isAnonymous) { + return null; + } return $context->dataSource->findUser($comment->authorId); } diff --git a/examples/01-blog/Blog/Type/Enum/ContentFormatEnum.php b/examples/01-blog/Blog/Type/Enum/ContentFormatEnum.php index cccc388..162d457 100644 --- a/examples/01-blog/Blog/Type/Enum/ContentFormatEnum.php +++ b/examples/01-blog/Blog/Type/Enum/ContentFormatEnum.php @@ -11,6 +11,7 @@ class ContentFormatEnum extends BaseType public function __construct() { + // Option #1: Define type using composition over inheritance, see ImageSizeEnumType for inheritance option $this->definition = new EnumType([ 'name' => 'ContentFormatEnum', 'values' => [self::FORMAT_TEXT, self::FORMAT_HTML] diff --git a/examples/01-blog/Blog/Type/Enum/ImageSizeEnumType.php b/examples/01-blog/Blog/Type/Enum/ImageSizeEnumType.php index 4a8569f..384fb5e 100644 --- a/examples/01-blog/Blog/Type/Enum/ImageSizeEnumType.php +++ b/examples/01-blog/Blog/Type/Enum/ImageSizeEnumType.php @@ -2,24 +2,23 @@ namespace GraphQL\Examples\Blog\Type\Enum; use GraphQL\Examples\Blog\Data\Image; -use GraphQL\Examples\Blog\Type\BaseType; use GraphQL\Type\Definition\EnumType; -class ImageSizeEnumType extends BaseType +class ImageSizeEnumType extends EnumType { - /** - * ImageSizeEnumType constructor. - */ public function __construct() { - $this->definition = new EnumType([ - 'name' => 'ImageSizeEnum', + // Option #2: Define enum type using inheritance + $config = [ + // Note: 'name' option is not needed in this form - it will be inferred from className 'values' => [ 'ICON' => Image::SIZE_ICON, 'SMALL' => Image::SIZE_SMALL, 'MEDIUM' => Image::SIZE_MEDIUM, 'ORIGINAL' => Image::SIZE_ORIGINAL ] - ]); + ]; + + parent::__construct($config); } } diff --git a/examples/01-blog/Blog/Type/Field/HtmlField.php b/examples/01-blog/Blog/Type/Field/HtmlField.php index 59c9bd8..6c92f60 100644 --- a/examples/01-blog/Blog/Type/Field/HtmlField.php +++ b/examples/01-blog/Blog/Type/Field/HtmlField.php @@ -10,6 +10,9 @@ class HtmlField { $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 [ 'name' => $name, 'type' => $types->string(), diff --git a/examples/01-blog/Blog/Type/FieldDefinitions.php b/examples/01-blog/Blog/Type/FieldDefinitions.php deleted file mode 100644 index f41b282..0000000 --- a/examples/01-blog/Blog/Type/FieldDefinitions.php +++ /dev/null @@ -1,31 +0,0 @@ -types = $types; - } - - private $htmlField; - - public function htmlField($name, $objectKey = null) - { - $objectKey = $objectKey ?: $name; - - return $this->htmlField ?: $this->htmlField = [ - 'name' => $name, - ]; - } -} diff --git a/examples/01-blog/Blog/Type/ImageType.php b/examples/01-blog/Blog/Type/ImageType.php index 1508aa7..1a3f69e 100644 --- a/examples/01-blog/Blog/Type/ImageType.php +++ b/examples/01-blog/Blog/Type/ImageType.php @@ -7,11 +7,12 @@ use GraphQL\Examples\Blog\TypeSystem; use GraphQL\Type\Definition\EnumType; use GraphQL\Type\Definition\ObjectType; -class ImageType extends BaseType +class ImageType extends ObjectType { 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', 'fields' => [ 'id' => $types->id(), @@ -43,7 +44,9 @@ class ImageType extends BaseType } ] ] - ]); + ]; + + parent::__construct($config); } public function resolveUrl(Image $value, $args, AppContext $context) diff --git a/examples/01-blog/Blog/Type/MentionType.php b/examples/01-blog/Blog/Type/MentionType.php index 66276d7..330a741 100644 --- a/examples/01-blog/Blog/Type/MentionType.php +++ b/examples/01-blog/Blog/Type/MentionType.php @@ -11,6 +11,7 @@ class MentionType extends BaseType { public function __construct(TypeSystem $types) { + // Option #1: using composition over inheritance to define type, see ImageType for inheritance example $this->definition = new UnionType([ 'name' => 'Mention', 'types' => function() use ($types) { diff --git a/examples/01-blog/Blog/Type/NodeType.php b/examples/01-blog/Blog/Type/NodeType.php index 1ddde4d..c2539e2 100644 --- a/examples/01-blog/Blog/Type/NodeType.php +++ b/examples/01-blog/Blog/Type/NodeType.php @@ -9,12 +9,9 @@ use GraphQL\Type\Definition\InterfaceType; class NodeType extends BaseType { - /** - * NodeType constructor. - * @param 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([ 'name' => 'Node', 'fields' => [ diff --git a/examples/01-blog/Blog/Type/QueryType.php b/examples/01-blog/Blog/Type/QueryType.php index d27481d..1173b0e 100644 --- a/examples/01-blog/Blog/Type/QueryType.php +++ b/examples/01-blog/Blog/Type/QueryType.php @@ -11,6 +11,7 @@ class QueryType extends BaseType { public function __construct(TypeSystem $types) { + // Option #1: using composition over inheritance to define type, see ImageType for inheritance example $this->definition = new ObjectType([ 'name' => 'Query', 'fields' => [ diff --git a/examples/01-blog/Blog/Type/Scalar/EmailType.php b/examples/01-blog/Blog/Type/Scalar/EmailType.php index b3548dd..9800ba4 100644 --- a/examples/01-blog/Blog/Type/Scalar/EmailType.php +++ b/examples/01-blog/Blog/Type/Scalar/EmailType.php @@ -10,6 +10,7 @@ class EmailType extends BaseType { public function __construct() { + // Option #1: define scalar types using composition (see UrlType fo option #2 using inheritance) $this->definition = new CustomScalarType([ 'name' => 'Email', 'serialize' => [$this, 'serialize'], diff --git a/examples/01-blog/Blog/Type/Scalar/UrlTypeDefinition.php b/examples/01-blog/Blog/Type/Scalar/UrlType.php similarity index 88% rename from examples/01-blog/Blog/Type/Scalar/UrlTypeDefinition.php rename to examples/01-blog/Blog/Type/Scalar/UrlType.php index 80fc156..675e38b 100644 --- a/examples/01-blog/Blog/Type/Scalar/UrlTypeDefinition.php +++ b/examples/01-blog/Blog/Type/Scalar/UrlType.php @@ -5,14 +5,9 @@ use GraphQL\Language\AST\StringValue; use GraphQL\Type\Definition\ScalarType; use GraphQL\Utils; -/** - * Class UrlTypeDefinition - * - * @package GraphQL\Examples\Blog\Type\Scalar - */ -class UrlTypeDefinition extends ScalarType +class UrlType 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. diff --git a/examples/01-blog/Blog/Type/StoryType.php b/examples/01-blog/Blog/Type/StoryType.php index 45ba212..a1d4e74 100644 --- a/examples/01-blog/Blog/Type/StoryType.php +++ b/examples/01-blog/Blog/Type/StoryType.php @@ -23,6 +23,7 @@ class StoryType extends BaseType public function __construct(TypeSystem $types) { + // Option #1: using composition over inheritance to define type, see ImageType for inheritance example $this->definition = new ObjectType([ 'name' => 'Story', 'fields' => function() use ($types) { diff --git a/examples/01-blog/Blog/Type/UserType.php b/examples/01-blog/Blog/Type/UserType.php index bf33c8d..e5d4a43 100644 --- a/examples/01-blog/Blog/Type/UserType.php +++ b/examples/01-blog/Blog/Type/UserType.php @@ -11,6 +11,7 @@ class UserType extends BaseType { public function __construct(TypeSystem $types) { + // Option #1: using composition over inheritance to define type, see ImageType for inheritance example $this->definition = new ObjectType([ 'name' => 'User', 'fields' => function() use ($types) { diff --git a/examples/01-blog/Blog/TypeSystem.php b/examples/01-blog/Blog/TypeSystem.php index 045414b..6cd9ca4 100644 --- a/examples/01-blog/Blog/TypeSystem.php +++ b/examples/01-blog/Blog/TypeSystem.php @@ -5,13 +5,12 @@ use GraphQL\Examples\Blog\Type\CommentType; use GraphQL\Examples\Blog\Type\Enum\ContentFormatEnum; use GraphQL\Examples\Blog\Type\Enum\ImageSizeEnumType; use GraphQL\Examples\Blog\Type\Field\HtmlField; -use GraphQL\Examples\Blog\Type\FieldDefinitions; use GraphQL\Examples\Blog\Type\MentionType; use GraphQL\Examples\Blog\Type\NodeType; use GraphQL\Examples\Blog\Type\QueryType; use GraphQL\Examples\Blog\Type\Scalar\EmailType; 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\ImageType; use GraphQL\Type\Definition\ListOfType; @@ -129,15 +128,15 @@ class TypeSystem public function email() { - return $this->emailType ?: ($this->emailType = new EmailType); + return $this->emailType ?: ($this->emailType = new EmailType()); } /** - * @return UrlTypeDefinition + * @return UrlType */ public function url() { - return $this->urlType ?: ($this->urlType = new UrlTypeDefinition); + return $this->urlType ?: ($this->urlType = new UrlType()); } /**