Simplified blog example

This commit is contained in:
vladar 2016-11-06 21:33:13 +07:00
parent e69667c633
commit 360bf39c9b
12 changed files with 236 additions and 218 deletions

View File

@ -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;
}

View File

@ -1,6 +1,5 @@
<?php
namespace GraphQL\Examples\Blog\Data;
use GraphQL\Utils;
/**
* Class DataSource
@ -12,14 +11,17 @@ use GraphQL\Utils;
*/
class DataSource
{
private $users = [];
private $stories = [];
private $storyLikes = [];
private $comments = [];
private static $users = [];
private static $stories = [];
private static $storyLikes = [];
private static $comments = [];
private static $storyComments = [];
private static $commentReplies = [];
private static $storyMentions = [];
public function __construct()
public static function init()
{
$this->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' => '<h1>GraphQL is awesome!</h1>']),
'2' => new Story(['id' => '2', 'authorId' => '1', 'body' => '<a>Test this</a>']),
'3' => new Story(['id' => '3', 'authorId' => '3', 'body' => "This\n<br>story\n<br>spans\n<br>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 <b>#1</b>', '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] :[];
}
}

View File

@ -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);
}
}

View File

@ -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};

View File

@ -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");
}

View File

@ -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();
}
}
}

View File

@ -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()

View File

@ -1,30 +1,29 @@
<?php
namespace GraphQL\Examples\Blog\Type;
use GraphQL\Examples\Blog\AppContext;
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\UnionType;
class MentionType extends BaseType
class SearchResultType 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 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();
}
}
]);

View File

@ -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']);
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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(