From 360bf39c9b14fbf16aaf067e09753ea87c6c9030 Mon Sep 17 00:00:00 2001 From: vladar Date: Sun, 6 Nov 2016 21:33:13 +0700 Subject: [PATCH] Simplified blog example --- examples/01-blog/Blog/AppContext.php | 7 +- examples/01-blog/Blog/Data/DataSource.php | 102 ++++++++++-------- examples/01-blog/Blog/Type/CommentType.php | 41 +++---- .../01-blog/Blog/Type/Field/HtmlField.php | 10 +- examples/01-blog/Blog/Type/ImageType.php | 18 ++-- examples/01-blog/Blog/Type/NodeType.php | 18 ++-- examples/01-blog/Blog/Type/QueryType.php | 35 +++--- .../{MentionType.php => SearchResultType.php} | 21 ++-- examples/01-blog/Blog/Type/StoryType.php | 61 ++++++----- examples/01-blog/Blog/Type/UserType.php | 34 +++--- .../Blog/{TypeSystem.php => Types.php} | 92 ++++++++-------- examples/01-blog/graphql.php | 15 +-- 12 files changed, 236 insertions(+), 218 deletions(-) rename examples/01-blog/Blog/Type/{MentionType.php => SearchResultType.php} (53%) rename examples/01-blog/Blog/{TypeSystem.php => Types.php} (57%) diff --git a/examples/01-blog/Blog/AppContext.php b/examples/01-blog/Blog/AppContext.php index 2113b68..2b42406 100644 --- a/examples/01-blog/Blog/AppContext.php +++ b/examples/01-blog/Blog/AppContext.php @@ -9,7 +9,7 @@ use GraphQL\Utils; * Class AppContext * Instance available in all GraphQL resolvers as 3rd argument * - * @package GraphQL\Examples\Social + * @package GraphQL\Examples\Blog */ class AppContext { @@ -27,9 +27,4 @@ class AppContext * @var \mixed */ public $request; - - /** - * @var DataSource - */ - public $dataSource; } diff --git a/examples/01-blog/Blog/Data/DataSource.php b/examples/01-blog/Blog/Data/DataSource.php index fdb0e24..09c1e02 100644 --- a/examples/01-blog/Blog/Data/DataSource.php +++ b/examples/01-blog/Blog/Data/DataSource.php @@ -1,6 +1,5 @@ users = [ + self::$users = [ '1' => new User([ 'id' => '1', 'email' => 'john@example.com', @@ -40,19 +42,19 @@ class DataSource ]), ]; - $this->stories = [ + self::$stories = [ '1' => new Story(['id' => '1', 'authorId' => '1', 'body' => '

GraphQL is awesome!

']), '2' => new Story(['id' => '2', 'authorId' => '1', 'body' => 'Test this']), '3' => new Story(['id' => '3', 'authorId' => '3', 'body' => "This\n
story\n
spans\n
newlines"]), ]; - $this->storyLikes = [ + self::$storyLikes = [ '1' => ['1', '2', '3'], '2' => [], '3' => ['1'] ]; - $this->comments = [ + self::$comments = [ // thread #1: '100' => new Comment(['id' => '100', 'authorId' => '3', 'storyId' => '1', 'body' => 'Likes']), '110' => new Comment(['id' =>'110', 'authorId' =>'2', 'storyId' => '1', 'body' => 'Reply #1', 'parentId' => '100']), @@ -73,57 +75,69 @@ class DataSource '500' => new Comment(['id' => '500', 'authorId' => '2', 'storyId' => '2', 'body' => 'Nice!']), ]; - $this->storyComments = [ + self::$storyComments = [ '1' => ['100', '200', '300'], '2' => ['400', '500'] ]; - $this->commentReplies = [ + self::$commentReplies = [ '100' => ['110', '120', '130'], '110' => ['111', '112', '113', '114', '115', '116', '117'], ]; - $this->storyMentions = [ + self::$storyMentions = [ '1' => [ - $this->users['2'] + self::$users['2'] ], '2' => [ - $this->stories['1'], - $this->users['3'] + self::$stories['1'], + self::$users['3'] ] ]; } - public function findUser($id) + public static function findUser($id) { - return isset($this->users[$id]) ? $this->users[$id] : null; + return isset(self::$users[$id]) ? self::$users[$id] : null; } - public function findStory($id) + public static function findStory($id) { - return isset($this->stories[$id]) ? $this->stories[$id] : null; + return isset(self::$stories[$id]) ? self::$stories[$id] : null; } - public function findComment($id) + public static function findComment($id) { - return isset($this->comments[$id]) ? $this->comments[$id] : null; + return isset(self::$comments[$id]) ? self::$comments[$id] : null; } - public function findLastStoryFor($authorId) + public static function findLastStoryFor($authorId) { - $storiesFound = array_filter($this->stories, function(Story $story) use ($authorId) { + $storiesFound = array_filter(self::$stories, function(Story $story) use ($authorId) { return $story->authorId == $authorId; }); return !empty($storiesFound) ? $storiesFound[count($storiesFound) - 1] : null; } - public function isLikedBy($storyId, $userId) + public static function findLikes($storyId, $limit) { - $subscribers = isset($this->storyLikes[$storyId]) ? $this->storyLikes[$storyId] : []; + $likes = isset(self::$storyLikes[$storyId]) ? self::$storyLikes[$storyId] : []; + $result = array_map( + function($userId) { + return self::$users[$userId]; + }, + $likes + ); + return array_slice($result, 0, $limit); + } + + public static function isLikedBy($storyId, $userId) + { + $subscribers = isset(self::$storyLikes[$storyId]) ? self::$storyLikes[$storyId] : []; return in_array($userId, $subscribers); } - public function getUserPhoto($userId, $size) + public static function getUserPhoto($userId, $size) { return new Image([ 'id' => $userId, @@ -134,59 +148,59 @@ class DataSource ]); } - public function findLatestStory() + public static function findLatestStory() { - return array_pop($this->stories); + return array_pop(self::$stories); } - public function findStories($limit, $afterId = null) + public static function findStories($limit, $afterId = null) { - $start = $afterId ? (int) array_search($afterId, array_keys($this->stories)) + 1 : 0; - return array_slice(array_values($this->stories), $start, $limit); + $start = $afterId ? (int) array_search($afterId, array_keys(self::$stories)) + 1 : 0; + return array_slice(array_values(self::$stories), $start, $limit); } - public function findComments($storyId, $limit = 5, $afterId = null) + public static function findComments($storyId, $limit = 5, $afterId = null) { - $storyComments = isset($this->storyComments[$storyId]) ? $this->storyComments[$storyId] : []; + $storyComments = isset(self::$storyComments[$storyId]) ? self::$storyComments[$storyId] : []; $start = isset($after) ? (int) array_search($afterId, $storyComments) + 1 : 0; $storyComments = array_slice($storyComments, $start, $limit); return array_map( function($commentId) { - return $this->comments[$commentId]; + return self::$comments[$commentId]; }, $storyComments ); } - public function findReplies($commentId, $limit = 5, $afterId = null) + public static function findReplies($commentId, $limit = 5, $afterId = null) { - $commentReplies = isset($this->commentReplies[$commentId]) ? $this->commentReplies[$commentId] : []; + $commentReplies = isset(self::$commentReplies[$commentId]) ? self::$commentReplies[$commentId] : []; $start = isset($after) ? (int) array_search($afterId, $commentReplies) + 1: 0; $commentReplies = array_slice($commentReplies, $start, $limit); return array_map( function($replyId) { - return $this->comments[$replyId]; + return self::$comments[$replyId]; }, $commentReplies ); } - public function countComments($storyId) + public static function countComments($storyId) { - return isset($this->storyComments[$storyId]) ? count($this->storyComments[$storyId]) : 0; + return isset(self::$storyComments[$storyId]) ? count(self::$storyComments[$storyId]) : 0; } - public function countReplies($commentId) + public static function countReplies($commentId) { - return isset($this->commentReplies[$commentId]) ? count($this->commentReplies[$commentId]) : 0; + return isset(self::$commentReplies[$commentId]) ? count(self::$commentReplies[$commentId]) : 0; } - public function findStoryMentions($storyId) + public static function findStoryMentions($storyId) { - return isset($this->storyMentions[$storyId]) ? $this->storyMentions[$storyId] :[]; + return isset(self::$storyMentions[$storyId]) ? self::$storyMentions[$storyId] :[]; } } diff --git a/examples/01-blog/Blog/Type/CommentType.php b/examples/01-blog/Blog/Type/CommentType.php index 57a7658..b3cdeac 100644 --- a/examples/01-blog/Blog/Type/CommentType.php +++ b/examples/01-blog/Blog/Type/CommentType.php @@ -3,36 +3,37 @@ namespace GraphQL\Examples\Blog\Type; use GraphQL\Examples\Blog\AppContext; use GraphQL\Examples\Blog\Data\Comment; -use GraphQL\Examples\Blog\TypeSystem; +use GraphQL\Examples\Blog\Data\DataSource; +use GraphQL\Examples\Blog\Types; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\ResolveInfo; class CommentType extends BaseType { - public function __construct(TypeSystem $types) + public function __construct() { // Option #1: using composition over inheritance to define type, see ImageType for inheritance example $this->definition = new ObjectType([ 'name' => 'Comment', - 'fields' => function() use ($types) { + 'fields' => function() { return [ - 'id' => $types->id(), - 'author' => $types->user(), - 'parent' => $types->comment(), - 'isAnonymous' => $types->boolean(), + 'id' => Types::id(), + 'author' => Types::user(), + 'parent' => Types::comment(), + 'isAnonymous' => Types::boolean(), 'replies' => [ - 'type' => $types->listOf($types->comment()), + 'type' => Types::listOf(Types::comment()), 'args' => [ - 'after' => $types->int(), + 'after' => Types::int(), 'limit' => [ - 'type' => $types->int(), + 'type' => Types::int(), 'defaultValue' => 5 ] ] ], - 'totalReplyCount' => $types->int(), + 'totalReplyCount' => Types::int(), - $types->htmlField('body') + Types::htmlField('body') ]; }, 'resolveField' => function($value, $args, $context, ResolveInfo $info) { @@ -45,30 +46,30 @@ class CommentType extends BaseType ]); } - public function author(Comment $comment, $args, AppContext $context) + public function author(Comment $comment) { if ($comment->isAnonymous) { return null; } - return $context->dataSource->findUser($comment->authorId); + return DataSource::findUser($comment->authorId); } - public function parent(Comment $comment, $args, AppContext $context) + public function parent(Comment $comment) { if ($comment->parentId) { - return $context->dataSource->findComment($comment->parentId); + return DataSource::findComment($comment->parentId); } return null; } - public function replies(Comment $comment, $args, AppContext $context) + public function replies(Comment $comment, $args) { $args += ['after' => null]; - return $context->dataSource->findReplies($comment->id, $args['limit'], $args['after']); + return DataSource::findReplies($comment->id, $args['limit'], $args['after']); } - public function totalReplyCount(Comment $comment, $args, AppContext $context) + public function totalReplyCount(Comment $comment) { - return $context->dataSource->countReplies($comment->id); + return DataSource::countReplies($comment->id); } } diff --git a/examples/01-blog/Blog/Type/Field/HtmlField.php b/examples/01-blog/Blog/Type/Field/HtmlField.php index 6c92f60..f15ba6b 100644 --- a/examples/01-blog/Blog/Type/Field/HtmlField.php +++ b/examples/01-blog/Blog/Type/Field/HtmlField.php @@ -2,11 +2,11 @@ namespace GraphQL\Examples\Blog\Type\Field; use GraphQL\Examples\Blog\Type\Enum\ContentFormatEnum; -use GraphQL\Examples\Blog\TypeSystem; +use GraphQL\Examples\Blog\Types; class HtmlField { - public static function build(TypeSystem $types, $name, $objectKey = null) + public static function build($name, $objectKey = null) { $objectKey = $objectKey ?: $name; @@ -15,13 +15,13 @@ class HtmlField // (for example when it is a part of some interface) return [ 'name' => $name, - 'type' => $types->string(), + 'type' => Types::string(), 'args' => [ 'format' => [ - 'type' => $types->contentFormatEnum(), + 'type' => Types::contentFormatEnum(), 'defaultValue' => ContentFormatEnum::FORMAT_HTML ], - 'maxLength' => $types->int() + 'maxLength' => Types::int() ], 'resolve' => function($object, $args) use ($objectKey) { $html = $object->{$objectKey}; diff --git a/examples/01-blog/Blog/Type/ImageType.php b/examples/01-blog/Blog/Type/ImageType.php index 1a3f69e..90b8555 100644 --- a/examples/01-blog/Blog/Type/ImageType.php +++ b/examples/01-blog/Blog/Type/ImageType.php @@ -3,42 +3,42 @@ namespace GraphQL\Examples\Blog\Type; use GraphQL\Examples\Blog\AppContext; use GraphQL\Examples\Blog\Data\Image; -use GraphQL\Examples\Blog\TypeSystem; +use GraphQL\Examples\Blog\Types; use GraphQL\Type\Definition\EnumType; use GraphQL\Type\Definition\ObjectType; class ImageType extends ObjectType { - public function __construct(TypeSystem $types) + public function __construct() { // Option #2: define type using inheritance, see any other object type for compositional example $config = [ 'name' => 'ImageType', 'fields' => [ - 'id' => $types->id(), + 'id' => Types::id(), 'type' => new EnumType([ 'name' => 'ImageTypeEnum', 'values' => [ 'USERPIC' => Image::TYPE_USERPIC ] ]), - 'size' => $types->imageSizeEnum(), - 'width' => $types->int(), - 'height' => $types->int(), + 'size' => Types::imageSizeEnum(), + 'width' => Types::int(), + 'height' => Types::int(), 'url' => [ - 'type' => $types->url(), + 'type' => Types::url(), 'resolve' => [$this, 'resolveUrl'] ], // Just for the sake of example 'fieldWithError' => [ - 'type' => $types->string(), + 'type' => Types::string(), 'resolve' => function() { throw new \Exception("Field with exception"); } ], 'nonNullFieldWithError' => [ - 'type' => $types->nonNull($types->string()), + 'type' => Types::nonNull(Types::string()), 'resolve' => function() { throw new \Exception("Non-null field with exception"); } diff --git a/examples/01-blog/Blog/Type/NodeType.php b/examples/01-blog/Blog/Type/NodeType.php index c2539e2..7a60288 100644 --- a/examples/01-blog/Blog/Type/NodeType.php +++ b/examples/01-blog/Blog/Type/NodeType.php @@ -4,33 +4,31 @@ namespace GraphQL\Examples\Blog\Type; use GraphQL\Examples\Blog\Data\Story; use GraphQL\Examples\Blog\Data\User; use GraphQL\Examples\Blog\Data\Image; -use GraphQL\Examples\Blog\TypeSystem; +use GraphQL\Examples\Blog\Types; use GraphQL\Type\Definition\InterfaceType; class NodeType extends BaseType { - public function __construct(TypeSystem $types) + public function __construct() { // Option #1: using composition over inheritance to define type, see ImageType for inheritance example $this->definition = new InterfaceType([ 'name' => 'Node', 'fields' => [ - 'id' => $types->id() + 'id' => Types::id() ], - 'resolveType' => function ($object) use ($types) { - return $this->resolveType($object, $types); - } + 'resolveType' => [$this, 'resolveType'] ]); } - public function resolveType($object, TypeSystem $types) + public function resolveType($object, Types $types) { if ($object instanceof User) { - return $types->user(); + return Types::user(); } else if ($object instanceof Image) { - return $types->image(); + return Types::image(); } else if ($object instanceof Story) { - return $types->story(); + return Types::story(); } } } diff --git a/examples/01-blog/Blog/Type/QueryType.php b/examples/01-blog/Blog/Type/QueryType.php index 1173b0e..c3f459b 100644 --- a/examples/01-blog/Blog/Type/QueryType.php +++ b/examples/01-blog/Blog/Type/QueryType.php @@ -2,51 +2,52 @@ namespace GraphQL\Examples\Blog\Type; use GraphQL\Examples\Blog\AppContext; -use GraphQL\Examples\Blog\TypeSystem; +use GraphQL\Examples\Blog\Data\DataSource; +use GraphQL\Examples\Blog\Types; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\ResolveInfo; use GraphQL\Type\Definition\Type; class QueryType extends BaseType { - public function __construct(TypeSystem $types) + public function __construct() { // Option #1: using composition over inheritance to define type, see ImageType for inheritance example $this->definition = new ObjectType([ 'name' => 'Query', 'fields' => [ 'user' => [ - 'type' => $types->user(), + 'type' => Types::user(), 'description' => 'Returns user by id (in range of 1-5)', 'args' => [ - 'id' => $types->nonNull($types->id()) + 'id' => Types::nonNull(Types::id()) ] ], 'viewer' => [ - 'type' => $types->user(), + 'type' => Types::user(), 'description' => 'Represents currently logged-in user (for the sake of example - simply returns user with id == 1)' ], 'stories' => [ - 'type' => $types->listOf($types->story()), + 'type' => Types::listOf(Types::story()), 'description' => 'Returns subset of stories posted for this blog', 'args' => [ 'after' => [ - 'type' => $types->id(), + 'type' => Types::id(), 'description' => 'Fetch stories listed after the story with this ID' ], 'limit' => [ - 'type' => $types->int(), + 'type' => Types::int(), 'description' => 'Number of stories to be returned', 'defaultValue' => 10 ] ] ], 'lastStoryPosted' => [ - 'type' => $types->story(), + 'type' => Types::story(), 'description' => 'Returns last story posted for this blog' ], 'deprecatedField' => [ - 'type' => $types->string(), + 'type' => Types::string(), 'deprecationReason' => 'This field is deprecated!' ], 'hello' => Type::string() @@ -57,25 +58,25 @@ class QueryType extends BaseType ]); } - public function user($val, $args, AppContext $context) + public function user($rootValue, $args) { - return $context->dataSource->findUser($args['id']); + return DataSource::findUser($args['id']); } - public function viewer($val, $args, AppContext $context) + public function viewer($rootValue, $args, AppContext $context) { return $context->viewer; } - public function stories($val, $args, AppContext $context) + public function stories($rootValue, $args) { $args += ['after' => null]; - return $context->dataSource->findStories($args['limit'], $args['after']); + return DataSource::findStories($args['limit'], $args['after']); } - public function lastStoryPosted($val, $args, AppContext $context) + public function lastStoryPosted() { - return $context->dataSource->findLatestStory(); + return DataSource::findLatestStory(); } public function hello() diff --git a/examples/01-blog/Blog/Type/MentionType.php b/examples/01-blog/Blog/Type/SearchResultType.php similarity index 53% rename from examples/01-blog/Blog/Type/MentionType.php rename to examples/01-blog/Blog/Type/SearchResultType.php index 330a741..b1df78a 100644 --- a/examples/01-blog/Blog/Type/MentionType.php +++ b/examples/01-blog/Blog/Type/SearchResultType.php @@ -1,30 +1,29 @@ definition = new UnionType([ - 'name' => 'Mention', - 'types' => function() use ($types) { + 'name' => 'SearchResultType', + 'types' => function() { return [ - $types->story(), - $types->user() + Types::story(), + Types::user() ]; }, - 'resolveType' => function($value) use ($types) { + 'resolveType' => function($value) { if ($value instanceof Story) { - return $types->story(); + return Types::story(); } else if ($value instanceof User) { - return $types->user(); + return Types::user(); } } ]); diff --git a/examples/01-blog/Blog/Type/StoryType.php b/examples/01-blog/Blog/Type/StoryType.php index a1d4e74..d4ee8e2 100644 --- a/examples/01-blog/Blog/Type/StoryType.php +++ b/examples/01-blog/Blog/Type/StoryType.php @@ -2,9 +2,9 @@ namespace GraphQL\Examples\Blog\Type; use GraphQL\Examples\Blog\AppContext; +use GraphQL\Examples\Blog\Data\DataSource; use GraphQL\Examples\Blog\Data\Story; -use GraphQL\Examples\Blog\Data\User; -use GraphQL\Examples\Blog\TypeSystem; +use GraphQL\Examples\Blog\Types; use GraphQL\Type\Definition\EnumType; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\ResolveInfo; @@ -21,31 +21,44 @@ class StoryType extends BaseType const UNLIKE = 'UNLIKE'; const REPLY = 'REPLY'; - public function __construct(TypeSystem $types) + public function __construct() { // Option #1: using composition over inheritance to define type, see ImageType for inheritance example $this->definition = new ObjectType([ 'name' => 'Story', - 'fields' => function() use ($types) { + 'fields' => function() { return [ - 'id' => $types->id(), - 'author' => $types->user(), - 'mentions' => $types->listOf($types->mention()), - 'totalCommentCount' => $types->int(), + 'id' => Types::id(), + 'author' => Types::user(), + 'mentions' => Types::listOf(Types::mention()), + 'totalCommentCount' => Types::int(), 'comments' => [ - 'type' => $types->listOf($types->comment()), + 'type' => Types::listOf(Types::comment()), 'args' => [ 'after' => [ - 'type' => $types->id(), + 'type' => Types::id(), 'description' => 'Load all comments listed after given comment ID' ], 'limit' => [ - 'type' => $types->int(), + 'type' => Types::int(), 'defaultValue' => 5 ] ] ], - 'affordances' => $types->listOf(new EnumType([ + 'likes' => [ + 'type' => Types::listOf(Types::user()), + 'args' => [ + 'limit' => [ + 'type' => Types::int(), + 'description' => 'Limit the number of recent likes returned', + 'defaultValue' => 5 + ] + ] + ], + 'likedBy' => [ + 'type' => Types::listOf(Types::user()), + ], + 'affordances' => Types::listOf(new EnumType([ 'name' => 'StoryAffordancesEnum', 'values' => [ self::EDIT, @@ -55,13 +68,13 @@ class StoryType extends BaseType self::REPLY ] ])), - 'hasViewerLiked' => $types->boolean(), + 'hasViewerLiked' => Types::boolean(), - $types->htmlField('body'), + Types::htmlField('body'), ]; }, 'interfaces' => [ - $types->node() + Types::node() ], 'resolveField' => function($value, $args, $context, ResolveInfo $info) { if (method_exists($this, $info->fieldName)) { @@ -73,15 +86,15 @@ class StoryType extends BaseType ]); } - public function author(Story $story, $args, AppContext $context) + public function author(Story $story) { - return $context->dataSource->findUser($story->authorId); + return DataSource::findUser($story->authorId); } public function affordances(Story $story, $args, AppContext $context) { - $isViewer = $context->viewer === $context->dataSource->findUser($story->authorId); - $isLiked = $context->dataSource->isLikedBy($story->id, $context->viewer->id); + $isViewer = $context->viewer === DataSource::findUser($story->authorId); + $isLiked = DataSource::isLikedBy($story->id, $context->viewer->id); if ($isViewer) { $affordances[] = self::EDIT; @@ -97,17 +110,17 @@ class StoryType extends BaseType public function hasViewerLiked(Story $story, $args, AppContext $context) { - return $context->dataSource->isLikedBy($story->id, $context->viewer->id); + return DataSource::isLikedBy($story->id, $context->viewer->id); } - public function totalCommentCount(Story $story, $args, AppContext $context) + public function totalCommentCount(Story $story) { - return $context->dataSource->countComments($story->id); + return DataSource::countComments($story->id); } - public function comments(Story $story, $args, AppContext $context) + public function comments(Story $story, $args) { $args += ['after' => null]; - return $context->dataSource->findComments($story->id, $args['limit'], $args['after']); + return DataSource::findComments($story->id, $args['limit'], $args['after']); } } diff --git a/examples/01-blog/Blog/Type/UserType.php b/examples/01-blog/Blog/Type/UserType.php index e5d4a43..0a7da72 100644 --- a/examples/01-blog/Blog/Type/UserType.php +++ b/examples/01-blog/Blog/Type/UserType.php @@ -2,38 +2,40 @@ namespace GraphQL\Examples\Blog\Type; use GraphQL\Examples\Blog\AppContext; +use GraphQL\Examples\Blog\Data\DataSource; use GraphQL\Examples\Blog\Data\User; -use GraphQL\Examples\Blog\TypeSystem; +use GraphQL\Examples\Blog\Types; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\ResolveInfo; class UserType extends BaseType { - public function __construct(TypeSystem $types) + public function __construct() { // Option #1: using composition over inheritance to define type, see ImageType for inheritance example $this->definition = new ObjectType([ 'name' => 'User', - 'fields' => function() use ($types) { + 'description' => 'Our blog authors', + 'fields' => function() { return [ - 'id' => $types->id(), - 'email' => $types->email(), + 'id' => Types::id(), + 'email' => Types::email(), 'photo' => [ - 'type' => $types->image(), + 'type' => Types::image(), 'description' => 'User photo URL', 'args' => [ - 'size' => $types->nonNull($types->imageSizeEnum()), + 'size' => Types::nonNull(Types::imageSizeEnum()), ] ], 'firstName' => [ - 'type' => $types->string(), + 'type' => Types::string(), ], 'lastName' => [ - 'type' => $types->string(), + 'type' => Types::string(), ], - 'lastStoryPosted' => $types->story(), + 'lastStoryPosted' => Types::story(), 'fieldWithError' => [ - 'type' => $types->string(), + 'type' => Types::string(), 'resolve' => function() { throw new \Exception("This is error field"); } @@ -41,7 +43,7 @@ class UserType extends BaseType ]; }, 'interfaces' => [ - $types->node() + Types::node() ], 'resolveField' => function($value, $args, $context, ResolveInfo $info) { if (method_exists($this, $info->fieldName)) { @@ -53,13 +55,13 @@ class UserType extends BaseType ]); } - public function photo(User $user, $args, AppContext $context) + public function photo(User $user, $args) { - return $context->dataSource->getUserPhoto($user->id, $args['size']); + return DataSource::getUserPhoto($user->id, $args['size']); } - public function lastStoryPosted(User $user, $args, AppContext $context) + public function lastStoryPosted(User $user) { - return $context->dataSource->findLastStoryFor($user->id); + return DataSource::findLastStoryFor($user->id); } } diff --git a/examples/01-blog/Blog/TypeSystem.php b/examples/01-blog/Blog/Types.php similarity index 57% rename from examples/01-blog/Blog/TypeSystem.php rename to examples/01-blog/Blog/Types.php index 6cd9ca4..da0d996 100644 --- a/examples/01-blog/Blog/TypeSystem.php +++ b/examples/01-blog/Blog/Types.php @@ -5,7 +5,7 @@ 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\MentionType; +use GraphQL\Examples\Blog\Type\SearchResultType; use GraphQL\Examples\Blog\Type\NodeType; use GraphQL\Examples\Blog\Type\QueryType; use GraphQL\Examples\Blog\Type\Scalar\EmailType; @@ -19,7 +19,7 @@ use GraphQL\Type\Definition\Type; use GraphQL\Type\DefinitionContainer; /** - * Class TypeSystem + * Class Types * * Acts as a registry and factory for your types. * @@ -28,115 +28,115 @@ use GraphQL\Type\DefinitionContainer; * * @package GraphQL\Examples\Blog */ -class TypeSystem +class Types { // Object types: - private $user; - private $story; - private $comment; - private $image; - private $query; + private static $user; + private static $story; + private static $comment; + private static $image; + private static $query; /** * @return UserType */ - public function user() + public static function user() { - return $this->user ?: ($this->user = new UserType($this)); + return self::$user ?: (self::$user = new UserType()); } /** * @return StoryType */ - public function story() + public static function story() { - return $this->story ?: ($this->story = new StoryType($this)); + return self::$story ?: (self::$story = new StoryType()); } /** * @return CommentType */ - public function comment() + public static function comment() { - return $this->comment ?: ($this->comment = new CommentType($this)); + return self::$comment ?: (self::$comment = new CommentType()); } /** * @return ImageType */ - public function image() + public static function image() { - return $this->image ?: ($this->image = new ImageType($this)); + return self::$image ?: (self::$image = new ImageType()); } /** * @return QueryType */ - public function query() + public static function query() { - return $this->query ?: ($this->query = new QueryType($this)); + return self::$query ?: (self::$query = new QueryType()); } // Interface types - private $node; + private static $node; /** * @return NodeType */ - public function node() + public static function node() { - return $this->node ?: ($this->node = new NodeType($this)); + return self::$node ?: (self::$node = new NodeType()); } // Unions types: - private $mention; + private static $mention; /** - * @return MentionType + * @return SearchResultType */ - public function mention() + public static function mention() { - return $this->mention ?: ($this->mention = new MentionType($this)); + return self::$mention ?: (self::$mention = new SearchResultType()); } // Enum types - private $imageSizeEnum; - private $contentFormatEnum; + private static $imageSizeEnum; + private static $contentFormatEnum; /** * @return ImageSizeEnumType */ - public function imageSizeEnum() + public static function imageSizeEnum() { - return $this->imageSizeEnum ?: ($this->imageSizeEnum = new ImageSizeEnumType()); + return self::$imageSizeEnum ?: (self::$imageSizeEnum = new ImageSizeEnumType()); } /** * @return ContentFormatEnum */ - public function contentFormatEnum() + public static function contentFormatEnum() { - return $this->contentFormatEnum ?: ($this->contentFormatEnum = new ContentFormatEnum()); + return self::$contentFormatEnum ?: (self::$contentFormatEnum = new ContentFormatEnum()); } // Custom Scalar types: - private $urlType; - private $emailType; + private static $urlType; + private static $emailType; - public function email() + public static function email() { - return $this->emailType ?: ($this->emailType = new EmailType()); + return self::$emailType ?: (self::$emailType = new EmailType()); } /** * @return UrlType */ - public function url() + public static function url() { - return $this->urlType ?: ($this->urlType = new UrlType()); + return self::$urlType ?: (self::$urlType = new UrlType()); } /** @@ -144,16 +144,16 @@ class TypeSystem * @param null $objectKey * @return array */ - public function htmlField($name, $objectKey = null) + public static function htmlField($name, $objectKey = null) { - return HtmlField::build($this, $name, $objectKey); + return HtmlField::build($name, $objectKey); } // Let's add internal types as well for consistent experience - public function boolean() + public static function boolean() { return Type::boolean(); } @@ -161,7 +161,7 @@ class TypeSystem /** * @return \GraphQL\Type\Definition\FloatType */ - public function float() + public static function float() { return Type::float(); } @@ -169,7 +169,7 @@ class TypeSystem /** * @return \GraphQL\Type\Definition\IDType */ - public function id() + public static function id() { return Type::id(); } @@ -177,7 +177,7 @@ class TypeSystem /** * @return \GraphQL\Type\Definition\IntType */ - public function int() + public static function int() { return Type::int(); } @@ -185,7 +185,7 @@ class TypeSystem /** * @return \GraphQL\Type\Definition\StringType */ - public function string() + public static function string() { return Type::string(); } @@ -194,7 +194,7 @@ class TypeSystem * @param Type|DefinitionContainer $type * @return ListOfType */ - public function listOf($type) + public static function listOf($type) { return new ListOfType($type); } @@ -203,7 +203,7 @@ class TypeSystem * @param Type|DefinitionContainer $type * @return NonNull */ - public function nonNull($type) + public static function nonNull($type) { return new NonNull($type); } diff --git a/examples/01-blog/graphql.php b/examples/01-blog/graphql.php index d4416ea..88d343a 100644 --- a/examples/01-blog/graphql.php +++ b/examples/01-blog/graphql.php @@ -3,7 +3,7 @@ // php -S localhost:8080 ./index.php require_once '../../vendor/autoload.php'; -use \GraphQL\Examples\Blog\TypeSystem; +use \GraphQL\Examples\Blog\Types; use \GraphQL\Examples\Blog\AppContext; use \GraphQL\Examples\Blog\Data\DataSource; use \GraphQL\Schema; @@ -27,17 +27,12 @@ if (!empty($_GET['debug'])) { } try { - // Initialize user-land registry/factory of our app types: - $typeSystem = new TypeSystem(); - - // Init stub data source - // (in real-world apps this might be Doctrine's EntityManager for instance, or just DB connection): - $dataSource = new DataSource(); + // Initialize our fake data source + DataSource::init(); // Prepare context that will be available in all field resolvers (as 3rd argument): $appContext = new AppContext(); - $appContext->viewer = $dataSource->findUser(1); // simulated "currently logged-in user" - $appContext->dataSource = $dataSource; + $appContext->viewer = DataSource::findUser('1'); // simulated "currently logged-in user" $appContext->rootUrl = 'http://localhost:8080'; $appContext->request = $_REQUEST; @@ -58,7 +53,7 @@ try { // GraphQL schema to be passed to query executor: $schema = new Schema([ - 'query' => $typeSystem->query() + 'query' => Types::query() ]); $result = GraphQL::execute(