A framework for serving GraphQL from Laravel

Overview

Lighthouse

Continuous Integration Code Coverage PHPStan StyleCI

Packagist Latest Stable Version GitHub license

Ask on Stack Overflow Get on Slack

A framework for serving GraphQL from Laravel

Lighthouse is a GraphQL framework that integrates with your Laravel application. It takes the best ideas of both and combines them to solve common tasks with ease and offer flexibility when you need it.

Documentation

The documentation lives at lighthouse-php.com.

A chinese translation is available at lighthouse-php.cn and is maintained over at https://github.com/haxibiao/lighthouse.

Get involved

Changelog

All notable changes to this project are documented in CHANGELOG.md.

Upgrade Guide

When upgrading between major versions of Lighthouse, consider UPGRADE.md.

Contributing

We welcome contributions of any kind, see how in CONTRIBUTING.md.

Security Vulnerabilities

If you discover a security vulnerability within Lighthouse, please email Benedikt Franke via [email protected] or visit https://tidelift.com/security.

Comments
  • [Docs] How to get a paginator using different models? @union or @interface directive

    [Docs] How to get a paginator using different models? @union or @interface directive

    Hi all,

    I'm currently experimenting with the following use case, which seems like a perfect task for the @union directive.

    I have an Image and a Slogan model that have very similar properties and I need to have a mixed list exposed by graphql, combining the two types into one list. This should be a paginator from the Relay perspective.

    From what I can read in the docs and unit tests, I'm not totally clear on how to go about the above situation. Eg. I don't want to specify a type as a requirement since I want to have both kind of results mixed in a single result set.

    Maybe the @interface directive is the way to go? Any pointers in the right direction are greatly appreciated ;-)

    Kind regards,

    Erik

    question 
    opened by 4levels 60
  • Simplify argument directive structure and optimize execution

    Simplify argument directive structure and optimize execution

    In a nutshell, this PR is sent for performance optimization.

    Architecture changes

    Make it handle the argument directives at the resolving time but not the parsing time.

    Changes

    1. Removed ArgMiddleware, using newly added interface ArgFilterDirective and ArgTransformerDirective and ArgValidationDirective instead.
    2. A lot easier to write an argument directive because we can deal with actual argument value within the handler method now.
    3. Handle underlying argument directives when the argument value is an input object.
    4. The @bcrypt directive also works on input object now (actually all "transformers" do so now).
    5. Simplified the @rule directive
    6. Removed the RuleFactory class and related classes.
    7. Evaluate the argument directives in the written order.

    Introduced a new class ErrorBuffer

    Currently, it is used for gathering errors generated from @rules directive.

    Also this error buffering mechanism may be very helpful when dealing with nested query error handling.

    Actually, I'm building a schema auto-generation framework based on Lighthouse, the crud validation system is pretty complex and I found I can't done without this error buffering mechanism, so for me, kills two birds with one stone šŸ˜Š

    Known issues

    This is not specific for this PR, but worth to mention I think. Because of #400 , even if we evaluate the ArgMiddleware::handleArgument at the resolving time, simplified the @rule directive, still can not get much performance gains. still there are a lot of unnecessary processing if we don't solve #400, hopefully one day it can be fixed.


    Resolver: #372

    opened by yaquawa 57
  • [Feat] Subscriptions (Pusher implementation)

    [Feat] Subscriptions (Pusher implementation)

    Related Issue(s)

    #88

    PR Type

    Feature

    Changes

    As I get through this implementation I'll be filling out documentation here so when it's ready for merge I can update the doc site's next branch.

    Subscriptions Overview

    This implementation of subscriptions allows users to leverage Pusher as their websocket server (removing the need of supporting your own websocket server). Most of the credit should be given to the Ruby implementation as they provided a great overview of how the backend should work.

    Requirements

    Install the Pusher PHP Server package

    composer require pusher/pusher-php-server
    

    Enable the extension in the lighthouse.php config file

    'extensions' => [
        // ...
        \Nuwave\Lighthouse\Schema\Extensions\SubscriptionExtension::class,
    ],
    

    Basic Setup

    TODO: Add description here...

    type Mutation {
        updatePost(input: UpdatePostInput!): Post
            # This will pipe the Post returned from this mutation to the 
            # PostUpdatedSubscription resolve function
            @broadcast(subscription: "postUpdated") 
    }
    
    type Subscription {
        postUpdated(author: ID): Post
            @subscription(class: "App\\GraphQL\\Subscriptions\\PostUpdatedSubscription")
    }
    

    Subscription Class

    TODO: Go through example showing all class methods... TODO: Create example that creates a custom topic name to help filter listeners...

    namespace App\GraphQL\Subscriptions;
    
    use Illuminate\Http\Request;
    use Nuwave\Lighthouse\Schema\Subscriptions\Subscriber;
    use Nuwave\Lighthouse\Schema\Types\GraphQLSubscription;
    
    class PostUpdatedSubscription extends GraphQLSubscription
    {
        /**
         * Check if subscriber can listen to the subscription.
         *
         * @param Subscriber $subscriber
         * @param Request    $request
         *
         * @return bool
         */
        public function authorize(Subscriber $subscriber, Request $request)
        {
            $user = $subscriber->context->user;
    
            return $user->hasPermission('some-permission');
        }
    
        /**
         * Filter subscribers who should receive subscription.
         *
         * @param Subscriber $subscriber
         * @param mixed      \App\Models\Event $root
         *
         * @return bool
         */
        public function filter(Subscriber $subscriber, $root)
        {
            $user = $subscriber->context->user;
    
            // Don't send the subscription update to the same
            // person who updated the post.
            return $root->updated_by !== $user->id;
        }
    }
    

    Firing a subscription via code

    Using an event listener

    namespace App\Listeners\Post;
    
    use App\Http\GraphQL\Subscriptions\PostUpdatedSubscription;
    use Nuwave\Lighthouse\Subscriptions\Contracts\BroadcastsSubscriptions;
    
    class BroadcastPostUpdated
    {
        /**
         * @var BroadcastsSubscriptions
         */
        protected $broadcaster;
    
        /**
         * @var BroadcastsSubscriptions
         */
        protected $subscription;
    
        /**
         * Create the event listener.
         *
         * @param BroadcastsSubscriptions  $broadcaster
         * @param PostUpdatedSubscription $subscription
         */
        public function __construct(
            BroadcastsSubscriptions $broadcaster, 
            PostUpdatedSubscription $subscription
        ) {
            $this->broadcaster = $broadcaster;
            $this->subscription = $subscription;
        }
    
        /**
         * Handle the event.
         *
         * @param PostUpdatedEvent $event
         */
        public function handle(PostUpdatedEvent $event)
        {
            $this->broadcaster->broadcast(
                $this->subscription, // <-- The subscription class you created
                'postUpdated', // <-- Name of the subscription field to broadcast
                $event->post // <-- The root object that will be passed into the subscription resolver
            );
        }
    }
    

    Apollo Link

    import { ApolloLink, Observable } from 'apollo-link';
    
    class PusherLink extends ApolloLink {
      constructor(options) {
        super();
        // Retain a handle to the Pusher client
        this.pusher = options.pusher;
      }
    
      request(operation, forward) {
        return new Observable(observer => {
          // Check the result of the operation
          forward(operation).subscribe({
            next: data => {
              // If the operation has the subscription extension, it's a subscription
              const subscriptionChannel = this._getChannel(
                data,
                operation
              );
    
              if (subscriptionChannel) {
                this._createSubscription(subscriptionChannel, observer);
              } else {
                // No subscription found in the response, pipe data through
                observer.next(data);
                observer.complete();
              }
            },
          });
        });
      }
    
      _getChannel(data, operation) {
        return !!data.extensions
          && !!data.extensions.lighthouse_subscriptions
          && !!data.extensions.lighthouse_subscriptions.channels
          ? data.extensions.lighthouse_subscriptions.channels[operation.operationName]
          : null;
      }
    
      _createSubscription(subscriptionChannel, observer) {
        const pusherChannel = this.pusher.subscribe(subscriptionChannel);
        // Subscribe for more update
        pusherChannel.bind('lighthouse-subscription', payload => {
          if (!payload.more) {
            // This is the end, the server says to unsubscribe
            this.pusher.unsubscribe(subscriptionChannel);
            observer.complete();
          }
          const result = payload.result;
          if (result) {
            // Send the new response to listeners
            observer.next(result);
          }
        });
      }
    }
    
    export default PusherLink;
    

    Breaking changes

    None (can be disabled by excluding the extension in the config)

    TODO Items

    • [x] Move namespace up a level
    • [x] Create queue option to push broadcaster to background
    • [x] Add Tests
    • [x] Create Docs
    opened by chrissm79 41
  • Allow complex validation of input types

    Allow complex validation of input types

    • [x] Added or updated tests
    • [x] Added Docs for all relevant versions
    • [x] Updated CHANGELOG.md

    Changes

    This PR adds the ability to add the @validate directive on input types, declaring that the value of the input type should be validated by a dedicated InputTypeValidator class. These classes can be automatically resolved based on the lighthouse.namespaces.validators config value, or based on the validator directive argument.

    Things I still need to do

    • [x] Make sure validation messages are also used

    Breaking changes None

    Notes This is very much WIP, but I would like some early help and review. I feel like Iā€™m onto something, but I also feel like it could/should be done in a different way.

    5.x 
    opened by megawubs 40
  • Can't get @group directive to work

    Can't get @group directive to work

    Lighthouse version: 2.1-beta.5 for lumen support

    Hello, i'm using lumen with lighthouse and everything is working perfectly except for the @group directive as i want to apply an auth middleware to a group of queries. Every time i try to execute one of the queries in that group it goes straight to the resolver without passing by the middleware first.

    I made sure that the middleware is working as when i apply the middleware in the lighthouse config it works perfectly and all the graphql requests pass by the middleware first before being handled by the graphql controller.

    This is my schema.graphql:

    scalar DateTime @scalar(class: "DateTime")
    
    type User{
       id: ID!,
       username: String,
       age: Int,
       notes: String,
       created_at: DateTime!,
       email: String,
       mobileNumber: String
    }
    
    type LoginResult{
       userid: String!,
       token: String!,
       msg: String
    }
    
    input LoginInput{
       username: String!,
       password: String! @bcrypt
    }
    
    type Query{
       login(mobileNumber: String!, password: String!): LoginResult! @field(resolver: "App\\GraphQL\\Queries\\Query@Login")
    }
    
    extend type Query @group(middleware: "jwt"){
       test: String! @field(resolver: "App\\GraphQL\\Queries\\Query@testQuery")
       getUsers: [User!]! @field(resolver: "App\\GraphQL\\Queries\\Query@GetUsers")
       getUserInfo: User! @field(resolver: "App\\GraphQL\\Queries\\Query@getUserInfo")
    }
    
    type Mutation{
       addUser(username: String!, age: Int!, notes: String, password: String! @bcrypt, mobileNumber:String!, email: String!): User! @create(model: "App\\Models\\User")
    }
    

    What could be the problem here?

    Thanks a lot for an amazing project btw

    bug 
    opened by EslamNasser 37
  • Create a real world tutorial to help everybody understand Laravel Lighthouse step by step

    Create a real world tutorial to help everybody understand Laravel Lighthouse step by step

    I am willing to provide most of the code to create a functional blog with auth using vue-apollo What problem does this feature proposal attempt to solve? This solves the getting started and the tutorial section of the docs with a real-world example, That will make more people or companies adopt Laravel Lighthouse into their projects.

    The docs and tutorials are not very detailed on how to solve certain important features that you will find in a real-world app. Which possible solutions should be considered? Creating a real-world blog to show the value of Laravel Lighthouse

    I don't know any other solutions to this problem.

    Thanks for looking over my proposal.

    docs 
    opened by wolfiton 36
  • [Feat] Make mutating directives transactional (@create and @update)

    [Feat] Make mutating directives transactional (@create and @update)

    • [x] Added or updated tests
    • [x] Added Docs for all relevant versions / is applicable when explaining nested mutation

    Wrap @create and @update directives in a transaction. This ensures that if any of the nested mutations within fail, no changes are made to the database.

    Breaking changes

    The default is now to use transactions for mutations, but this can be disabled in the config.

    opened by liepaja 35
  • Support for Apollo Federation

    Support for Apollo Federation

    Issuehunt badges

    A while ago Apollo introduced a new strategy for merging GraphQL schemas together in a more sensible way than schema stitching. It would be great to see this supported in Lighthouse too.

    https://www.apollographql.com/docs/apollo-server/federation/introduction/ https://www.apollographql.com/docs/apollo-server/federation/federation-spec/


    IssueHunt Summary

    Backers (Total: $0.00)

    Become a backer now!

    Or submit a pull request to get the deposits!

    Tips

    enhancement 
    opened by juusopiikkila 33
  • Lighthouse v2 Roadmap

    Lighthouse v2 Roadmap

    Overview

    I'll fill this section out when time permits but I'm currently working on v2.0 of Lighthouse. Spoiler alert, it's a large breaking change that (at the moment) doesn't have an upgrade path. That being said, with the new approach (schema first), the benefits that come with these breaking changes along w/ how much more the end-user can do with it (i.e., plugins) make this a requirement. I want Lighthouse to be approachable to anyone, doesn't require anything but a schema to get started, and provides the user w/ enough flexibility to extend Lighthouse to fit just about any project regardless of complexity.

    screen shot 2018-03-04 at 5 22 39 pm

    By defining the schema above, Lighthouse can:

    • Create and register User and Task types
    • Auto resolves the User hasMany task relationship
    • Auto resolves the Task belongsTo User relationship
    • Create a me query that requires and returns the authenticated user
    • Generates a createUser mutation that will autofill and create a new User w/ rule validation on the email argument
    • Generates a createTask mutation that will inject the authenticated user's id into the user_id argument (currently trying to figure out how to remove this argument from the schema the client sees). Mutation requires that the user can create tasks via a policy

    That's a lot it can do for you w/ only 31 lines and no code!!!

    Road to 2.0

    • [x] Directive system that the user can extend to resolve Nodes/Fields/Args
    • [x] Context argument injector
    • [x] create/update/delete autofill directives
    • [x] Query/Mutation middleware
    • [x] Ability to add scopes to filter relationships
    • [x] Use graphql-php built in Deferred class to handle relationships and prevent N+1
    • [x] Cache schema AST
    • [x] Ability to attach single directive to Argument/Field/Node
    • [x] Create Walkthrough video
    • [x] Update Documentation

    For those who want to check out the example project that the Walkthrough will be based off of, here it is! I'm going to try and work in as many built-in directives as possible to highlight what Lighthouse can do "out of the box" as I prep for the v2.0 release.

    After 2.0

    • [ ] Stubs for GraphQL types
    • [ ] Auto create/update/delete mutation generation for models (boolean in @model directive)
    • [ ] Custom Context - Allow creation of custom context when request comes in
    • [ ] Subscriptions (I had this working but there we some great updates made to Ratchet that I will need to investigate)
    opened by chrissm79 32
  • Event based request lifecycle

    Event based request lifecycle

    • [x] Added or updated tests
    • [x] Added Docs for all relevant versions

    Related Issue/Intent

    Unify how to hook into parts of the request lifecycle via events.

    This gives more control to end users as well as plugin developers, without having to learn a Lighthouse specific way of hooking into the lifecycle - it's all based on events.

    Changes

    What were previously extensions - Subscriptions, Tracing and Defer - was rebuilt using the event system.

    A new GraphQLRequest singleton was added to wrap the raw HTTP request and add GraphQL semantics and make it accessible throughout the codebase.

    Multiple events were added and documented in the API reference.

    Breaking changes

    This replaces the extension registration with a more flexible event-based approach.

    From a user perspective, extensions will have to be registered through a more standard ServiceProvider, rather then the Lighthouse config.

    enhancement 
    opened by spawnia 30
  • New GraphQL implementation

    New GraphQL implementation

    Hello Maintainers,

    We have been working on a new PHP implementation of the GraphQL specification and we are closing in on a version 1.0 release. I just wanted to stop by and mention this to see if you're interested in teaming up with us. There is a Slack for the project where we can invite you.

    The repository can be found here: https://github.com/digiaonline/graphql-php

    Best, Christoffer

    enhancement 
    opened by crisu83 30
  • Namespacing by separation of concerns

    Namespacing by separation of concerns

    I'm looking into implement Namespacing by separation of concerns, as detailed in Apollo's docs -- https://www.apollographql.com/docs/technotes/TN0012-namespacing-by-separation-of-concern/

    So rather than having

    createPost updatePost createUser createComment etc

    you end up with:

    post {
        update
        create 
    }
    
    user { 
        create 
        update 
    } 
    

    etc.

    But every time I attempt this with Lighthouse, I get "Could not locate a field resolver for the mutation: entries. Either add a resolver directive such as @all, @find or @create or add a resolver class through: php artisan lighthouse:mutation Entries",

    type EntriesMutations {
        acknowledge(input: acknowledgeEntries @spread): acknowledgePayload @field(resolver: "\\App\\GraphQL\\Mutations\\Entry\\Acknowledge")
    }
    
    extend type Mutation {
        entries: EntriesMutations!
    }
    
    input acknowledgeEntries {
        vesselId: ID! @rename(attribute: "vessel_id") @rules(apply: ["required"])
        userId: ID! @rules(apply: ["required"]) @rename(attribute: "user_id")
        dateRange: DateRange! @rules(apply: ["required"])
    }
    
    type acknowledgePayload {
        entries: [Entry!]!
    }
    
    mutation {
    	entries {
    		acknowledge(
    			input: {
    				vesselId: 5755
    				userId: 133
    				dateRange: { startsAt: "2022-12-01", endsAt: "2022-12-31" }
    			}
    		) {
    			entries {
    			    id
    			}
    		}
    	}
    }
    

    So I'm guessing this doesn't work out the box like it does with Apollo and I'd need to implement a custom resolver? Trouble is I have no idea what or how to even approach that

    opened by SlyDave 2
  • columns and columnsEnum doesn't work with Predefined Ordering

    columns and columnsEnum doesn't work with Predefined Ordering

    When trying to use the columns or columnsEnum arguments for the @orderBy directive, they do not work when used in Predefined Ordering, but work fine when apply to a field's arguments.

    example schema

    enum DepartmentPositionSortableColumns {
        RANK @enum(value: "rank")
        NAME @enum(value: "name")
    }
    
    type DepartmentPosition {
        id: ID!
        departmentId: Int! @rename(attribute: "department_id")
        name: String!
        rank: Int
        createdAt: DateTime @rename(attribute: "created_at")
        updatedAt: DateTime @rename(attribute: "updated_at")
    }
    
    type Department {
        id: ID!
        name: String!
        shortName: String! @rename(attribute: "short_name")
        colour: String!
        isHidden: Boolean! @rename(attribute: "is_hidden")
        createdAt: DateTime @rename(attribute: "created_at")
        updatedAt: DateTime @rename(attribute: "updated_at")
    
        departmentPositions: [DepartmentPosition!]! @hasMany(relation: "positions") @orderBy(columnsEnum: "DepartmentPositionSortableColumns")
    }
    
    extend type Query {
        departments: [Department!]! @all
    }
    

    query:

    {
    	departments {
    		name
    		departmentPositions {
    			name
    			rank
    		}
    	}
    }
    
    

    This throws

    			"debugMessage": "SQLSTATE[42S22]: Column not found: 1054 Unknown column '' in 'order clause' (SQL: select * from `department_positions` where `department_positions`.`department_id` in (1, 2, 3, 4, 5, 6, 8, 10, 11, 12) order by `` asc)",
    			"message": "Internal server error",
    

    Same occurs if you use columns, but if you use column "rank", it works just fine - but obviously only sorts by the single column.

    Expected behavior/Solution

    Sorting by multiple columns should be possible in Predefined Ordering.

    Steps to reproduce

    1. Create a schema
    2. Add Predefined Ordering to a field, use a enum or columns to apply multiple sort columns
    3. run a query against it

    Output/Logs

    Click to expand { "errors": [ { "debugMessage": "SQLSTATE[42S22]: Column not found: 1054 Unknown column '' in 'order clause' (SQL: select * from `department_positions` where `department_positions`.`department_id` in (1, 2, 3, 4, 5, 6, 8, 10, 11, 12) order by `` asc)", "message": "Internal server error", "extensions": { "category": "internal" }, "locations": [ { "line": 11, "column": 3 } ], "path": [ "departments", 0, "departmentPositions" ], "trace": [ { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Connection.php", "line": 672, "call": "Illuminate\\Database\\Connection::runQueryCallback()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Connection.php", "line": 376, "call": "Illuminate\\Database\\Connection::run()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Query\\Builder.php", "line": 2414, "call": "Illuminate\\Database\\Connection::select()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Query\\Builder.php", "line": 2402, "call": "Illuminate\\Database\\Query\\Builder::runSelect()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Query\\Builder.php", "line": 2936, "call": "Illuminate\\Database\\Query\\Builder::Illuminate\\Database\\Query\\{closure}()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Query\\Builder.php", "line": 2403, "call": "Illuminate\\Database\\Query\\Builder::onceWithColumns()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Eloquent\\Builder.php", "line": 625, "call": "Illuminate\\Database\\Query\\Builder::get()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Eloquent\\Builder.php", "line": 609, "call": "Illuminate\\Database\\Eloquent\\Builder::getModels()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Eloquent\\Relations\\Relation.php", "line": 195, "call": "Illuminate\\Database\\Eloquent\\Builder::get()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Eloquent\\Relations\\Relation.php", "line": 160, "call": "Illuminate\\Database\\Eloquent\\Relations\\Relation::get()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Eloquent\\Builder.php", "line": 673, "call": "Illuminate\\Database\\Eloquent\\Relations\\Relation::getEager()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Eloquent\\Builder.php", "line": 642, "call": "Illuminate\\Database\\Eloquent\\Builder::eagerLoadRelation()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Eloquent\\Collection.php", "line": 60, "call": "Illuminate\\Database\\Eloquent\\Builder::eagerLoadRelations()" }, { "file": "C:\\www\\workrest\\vendor\\nuwave\\lighthouse\\src\\Execution\\ModelsLoader\\SimpleModelsLoader.php", "line": 28, "call": "Illuminate\\Database\\Eloquent\\Collection::load()" }, { "file": "C:\\www\\workrest\\vendor\\nuwave\\lighthouse\\src\\Execution\\BatchLoader\\RelationBatchLoader.php", "line": 84, "call": "Nuwave\\Lighthouse\\Execution\\ModelsLoader\\SimpleModelsLoader::load()" }, { "file": "C:\\www\\workrest\\vendor\\nuwave\\lighthouse\\src\\Execution\\BatchLoader\\RelationBatchLoader.php", "line": 59, "call": "Nuwave\\Lighthouse\\Execution\\BatchLoader\\RelationBatchLoader::resolve()" }, { "file": "C:\\www\\workrest\\vendor\\webonyx\\graphql-php\\src\\Executor\\Promise\\Adapter\\SyncPromise.php", "line": 67, "call": "Nuwave\\Lighthouse\\Execution\\BatchLoader\\RelationBatchLoader::Nuwave\\Lighthouse\\Execution\\BatchLoader\\{closure}()" }, { "file": "C:\\www\\workrest\\vendor\\webonyx\\graphql-php\\src\\Executor\\Promise\\Adapter\\SyncPromise.php", "line": 53, "call": "GraphQL\\Executor\\Promise\\Adapter\\SyncPromise::GraphQL\\Executor\\Promise\\Adapter\\{closure}()" }, { "file": "C:\\www\\workrest\\vendor\\webonyx\\graphql-php\\src\\Executor\\Promise\\Adapter\\SyncPromiseAdapter.php", "line": 149, "call": "GraphQL\\Executor\\Promise\\Adapter\\SyncPromise::runQueue()" }, { "file": "C:\\www\\workrest\\vendor\\webonyx\\graphql-php\\src\\GraphQL.php", "line": 105, "call": "GraphQL\\Executor\\Promise\\Adapter\\SyncPromiseAdapter::wait()" }, { "file": "C:\\www\\workrest\\vendor\\nuwave\\lighthouse\\src\\GraphQL.php", "line": 270, "call": "GraphQL\\GraphQL::executeQuery()" }, { "file": "C:\\www\\workrest\\vendor\\nuwave\\lighthouse\\src\\GraphQL.php", "line": 204, "call": "Nuwave\\Lighthouse\\GraphQL::executeParsedQuery()" }, { "file": "C:\\www\\workrest\\vendor\\nuwave\\lighthouse\\src\\GraphQL.php", "line": 163, "call": "Nuwave\\Lighthouse\\GraphQL::parseAndExecuteQuery()" }, { "file": "C:\\www\\workrest\\vendor\\nuwave\\lighthouse\\src\\GraphQL.php", "line": 122, "call": "Nuwave\\Lighthouse\\GraphQL::executeOperation()" }, { "file": "C:\\www\\workrest\\vendor\\nuwave\\lighthouse\\src\\Support\\Utils.php", "line": 111, "call": "Nuwave\\Lighthouse\\GraphQL::Nuwave\\Lighthouse\\{closure}()" }, { "file": "C:\\www\\workrest\\vendor\\nuwave\\lighthouse\\src\\GraphQL.php", "line": 121, "call": "Nuwave\\Lighthouse\\Support\\Utils::mapEach()" }, { "file": "C:\\www\\workrest\\vendor\\nuwave\\lighthouse\\src\\Support\\Http\\Controllers\\GraphQLController.php", "line": 32, "call": "Nuwave\\Lighthouse\\GraphQL::executeOperationOrOperations()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\ControllerDispatcher.php", "line": 48, "call": "Nuwave\\Lighthouse\\Support\\Http\\Controllers\\GraphQLController::__invoke()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Route.php", "line": 262, "call": "Illuminate\\Routing\\ControllerDispatcher::dispatch()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Route.php", "line": 205, "call": "Illuminate\\Routing\\Route::runController()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php", "line": 721, "call": "Illuminate\\Routing\\Route::run()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php", "line": 128, "call": "Illuminate\\Routing\\Router::Illuminate\\Routing\\{closure}()" }, { "file": "C:\\www\\workrest\\vendor\\nuwave\\lighthouse\\src\\Support\\Http\\Middleware\\AttemptAuthentication.php", "line": 33, "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php", "line": 167, "call": "Nuwave\\Lighthouse\\Support\\Http\\Middleware\\AttemptAuthentication::handle()" }, { "file": "C:\\www\\workrest\\vendor\\nuwave\\lighthouse\\src\\Support\\Http\\Middleware\\AcceptJson.php", "line": 26, "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php", "line": 167, "call": "Nuwave\\Lighthouse\\Support\\Http\\Middleware\\AcceptJson::handle()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php", "line": 103, "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php", "line": 723, "call": "Illuminate\\Pipeline\\Pipeline::then()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php", "line": 698, "call": "Illuminate\\Routing\\Router::runRouteWithinStack()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php", "line": 662, "call": "Illuminate\\Routing\\Router::runRoute()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php", "line": 651, "call": "Illuminate\\Routing\\Router::dispatchToRoute()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php", "line": 167, "call": "Illuminate\\Routing\\Router::dispatch()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php", "line": 128, "call": "Illuminate\\Foundation\\Http\\Kernel::Illuminate\\Foundation\\Http\\{closure}()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\nova\\src\\Http\\Middleware\\ServeNova.php", "line": 23, "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php", "line": 167, "call": "Laravel\\Nova\\Http\\Middleware\\ServeNova::handle()" }, { "file": "C:\\www\\workrest\\vendor\\barryvdh\\laravel-debugbar\\src\\Middleware\\InjectDebugbar.php", "line": 66, "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php", "line": 167, "call": "Barryvdh\\Debugbar\\Middleware\\InjectDebugbar::handle()" }, { "file": "C:\\www\\workrest\\vendor\\fruitcake\\laravel-cors\\src\\HandleCors.php", "line": 37, "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php", "line": 167, "call": "Fruitcake\\Cors\\HandleCors::handle()" }, { "file": "C:\\www\\workrest\\vendor\\fideloper\\proxy\\src\\TrustProxies.php", "line": 57, "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php", "line": 167, "call": "Fideloper\\Proxy\\TrustProxies::handle()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest.php", "line": 21, "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull.php", "line": 31, "call": "Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest::handle()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php", "line": 167, "call": "Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull::handle()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest.php", "line": 21, "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\TrimStrings.php", "line": 40, "call": "Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest::handle()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php", "line": 167, "call": "Illuminate\\Foundation\\Http\\Middleware\\TrimStrings::handle()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize.php", "line": 27, "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php", "line": 167, "call": "Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize::handle()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance.php", "line": 86, "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php", "line": 167, "call": "Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance::handle()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php", "line": 103, "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php", "line": 142, "call": "Illuminate\\Pipeline\\Pipeline::then()" }, { "file": "C:\\www\\workrest\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php", "line": 111, "call": "Illuminate\\Foundation\\Http\\Kernel::sendRequestThroughRouter()" }, { "file": "C:\\www\\workrest\\public\\index.php", "line": 52, "call": "Illuminate\\Foundation\\Http\\Kernel::handle()" }, { "file": "C:\\www\\workrest\\server.php", "line": 21, "function": "require_once('C:\\www\\workrest\\public\\index.php')" } ] } ] }

    Lighthouse Version

    nuwave/lighthouse (v5.69.1)

    question 
    opened by SlyDave 3
  • Missing duplicated entities when querying Relay connections

    Missing duplicated entities when querying Relay connections

    It appears that Lighthouse is stripping duplicated entities when querying Relay connections.

    Example: Let's assume User has many Roles. We have 2 Roles and 2 Users. Each User has both Roles. When i now query all users only one user will have those roles.

    Expected behavior/Solution

    I would expect Lighthouse to return all Roles on both Users.

    Steps to reproduce

    1. Add new test to BelongsToManyDirectiveTest.php:
    final class BelongsToManyDirectiveTest extends DBTestCase
    {
    
        public function testQueryAllBelongsToManyRelayConnection(): void
        {
            $this->schema = /** @lang GraphQL */ '
            type User {
                roles: [Role!]! @belongsToMany(type: CONNECTION)
            }
    
            type Role {
                id: ID!
            }
    
            type Query {
                users: [User]! @all
            }
            ';
    
            $user = factory(User::class)->create();
            $this->be($user);
    
            $roles = factory(Role::class, 3)->create();
            $user->roles()->attach($roles);
    
            $user2 = factory(User::class)->create();
            $user2->roles()->attach($roles);
    
            $this->graphQL(/** @lang GraphQL */ '
            {
                users {
                    roles(first: 2) {
                        pageInfo {
                            hasNextPage
                        }
                        edges {
                            node {
                                id
                            }
                        }
                    }
                }
            }
            ')->assertJsonCount(2, 'data.users.0.roles.edges')
                ->assertJsonCount(2, 'data.users.1.roles.edges');
    
            // JSON will be something like:
            // {"data":{"users":[{"roles":{"pageInfo":{"hasNextPage":true},"edges":[]}},{"roles":{"pageInfo":{"hasNextPage":true},"edges":[{"node":{"id":"1"}},{"node":{"id":"2"}}]}}]}}
        }
    }
    
    1. Run the test (e.g. docker-compose exec php vendor/bin/phpunit --filter testQueryAllBelongsToManyRelayConnection)

    Output/Logs

    There was 1 failure:
    
    1) Tests\Integration\Schema\Directives\BelongsToManyDirectiveTest::testQueryAllBelongsToManyRelayConnection
    Failed to assert that the response count matched the expected 2
    Failed asserting that actual size 0 matches expected size 2.
    

    Lighthouse Version

    5.69.1

    needs reproduction 
    opened by nrueckmann 2
  • CanDirective args Argument value is of type 'ArrayValue', expected a scalar

    CanDirective args Argument value is of type 'ArrayValue', expected a scalar

    I use the GraphQL plugin for intellij suggested by the official docs, but it gives me an error when adding an array to args of @can

    Screen Shot 1401-10-07 at 19 10 32

    The message is:

    'createProperty' uses an illegal value for the argument 'args' on directive 'can'. Argument value is of type 'ArrayValue', expected a scalar
    

    Describe the bug

    type Mutation {
        createProperty(input: PropertyCreationInput @spread): Property @can(ability: "wp:role", args: [1,2], model: "App\\Models\\User")
    }
    

    So the args with [1,2] is the problem.

    This is the defined type at schema-directives.graphql which comes from /vendor/nuwave/lighthouse/src/Auth/CanDirective.php

    """
    Any constant literal value: https://graphql.github.io/graphql-spec/draft/#sec-Input-Values
    """
    scalar CanArgs
    

    Shouldn't that be something like instead?

    scalar CanArgs @scalar(class: "a class here")
    

    Expected behavior/Solution

    Steps to reproduce

    1. You can just use the example from the docs and add the args to it:
    type Mutation {
      createBlogPost(input: PostInput!): BlogPost
        @can(ability: "create", model: "App\\Post", args: [1,2])
    }
    
    1. You can now see createBlogPost is underlined and red in intellij with this error: 'createBlogPost' uses an illegal value for the argument 'args' on directive 'can'. Argument value is of type 'ArrayValue', expected a scalar

    Output/Logs

    Click to expand
    # Add in log output/error messages here
    

    Lighthouse Version : v5.67.0

    discussion 
    opened by Stevemoretz 2
  • `@can` throws 403 on non-default guard

    `@can` throws 403 on non-default guard

    When using @guard with any other guard than lighthouse config's default @can always returns 403

    @can should use the guard specified in @guard

    Inside CanDirective.php the code

    $this->gate->forUser($context->user());
    

    $context->user() returns null if using other guard, given Nuwave\Lighthouse\Auth\AuthServiceProvider.php guard() function only tries to use lighthouse or auth config file default guard.

    Lighthouse Version: v5.69.1

    discussion 
    opened by MissaelAnda 2
  • Do not cache schema when runing tests

    Do not cache schema when runing tests

    • [ ] Added or updated tests
    • [ ] Documented user facing changes
    • [x] Updated CHANGELOG.md

    Changes

    Lighthouse config file disables schema caching only if APP_ENV is set to local

    Out of the box, APP_ENV is set to testing when running PHPUnit tests (as defined in phpunit.xml).

    This means that when running tests using php artisan test or sail test the schema gets cached. Any further changes to schema require the file ./bootstrap/cache/lighthouse-schema.php to be deleted for the tests to pickup the schema changes, which I don't think is the intended behavior.

    This PR fixes that behavior by disabling cache for both local and testing application environments.

    Breaking changes

    opened by Deyjandi 0
Releases(v5.69.1)
  • v5.69.1(Dec 14, 2022)

    Fixed

    • Wrap base ResolveInfo class and extend it with public ArgumentSet $argumentSet in response to PHP 8.2 deprecating dynamic properties
    Source code(tar.gz)
    Source code(zip)
  • v5.69.0(Dec 13, 2022)

  • v5.68.1(Dec 7, 2022)

    Fixed

    • Avoid duplicated data in relation directives with paginator with non-unique foreign keys https://github.com/nuwave/lighthouse/pull/2252
    Source code(tar.gz)
    Source code(zip)
  • v5.68.0(Dec 4, 2022)

    Added

    • Allow interfaces to implement interfaces https://github.com/nuwave/lighthouse/pull/2248

    Fixed

    • Mark @clearCache directive repeatable https://github.com/nuwave/lighthouse/pull/2243
    Source code(tar.gz)
    Source code(zip)
  • v5.67.0(Nov 21, 2022)

  • v5.66.0(Nov 21, 2022)

  • v5.65.0(Nov 21, 2022)

  • v5.64.1(Nov 2, 2022)

  • v5.64.0(Nov 1, 2022)

    Changed

    • Allow requests with header X-Requested-With: XMLHttpRequest in EnsureXHR middleware https://github.com/nuwave/lighthouse/pull/2221
    Source code(tar.gz)
    Source code(zip)
  • v5.63.1(Oct 28, 2022)

  • v5.63.0(Oct 26, 2022)

  • v5.62.0(Oct 21, 2022)

  • v5.61.0(Sep 19, 2022)

  • v5.60.0(Sep 8, 2022)

    Added

    • Allow configuring security.disable_introspection through the env variable LIGHTHOUSE_SECURITY_DISABLE_INTROSPECTION https://github.com/nuwave/lighthouse/pull/2205
    Source code(tar.gz)
    Source code(zip)
  • v5.59.0(Sep 7, 2022)

  • v5.58.2(Aug 24, 2022)

  • v5.58.1(Aug 14, 2022)

  • v5.58.0(Aug 14, 2022)

    Added

    • Add description generation to LaravelEnumType based on BenSampo\Enum\Enum::getClassDescription() https://github.com/nuwave/lighthouse/pull/2177
    Source code(tar.gz)
    Source code(zip)
  • v5.57.6(Aug 14, 2022)

  • v5.57.5(Aug 9, 2022)

  • v5.57.4(Aug 5, 2022)

  • v5.57.3(Aug 4, 2022)

    Fixed

    • Fix cursor pagination always returning the first page when no fields from the pageInfo are requested https://github.com/nuwave/lighthouse/pull/2190
    Source code(tar.gz)
    Source code(zip)
  • v5.57.2(Aug 3, 2022)

  • v5.57.1(Aug 2, 2022)

  • v5.57.0(Jul 8, 2022)

    Added

    • Allow checking policies against resolved models in @can https://github.com/nuwave/lighthouse/pull/2159

    Fixed

    • Fix static analysis error in testing traits https://github.com/nuwave/lighthouse/pull/2180
    Source code(tar.gz)
    Source code(zip)
  • v5.56.0(Jul 4, 2022)

  • v5.55.1(Jun 22, 2022)

    Fixed

    • Always register TestingServiceProvider in order to ensure macros are recognized by Larastan https://github.com/nuwave/lighthouse/pull/2171
    Source code(tar.gz)
    Source code(zip)
  • v5.55.0(Jun 20, 2022)

    Changed

    • @paginate directive will use a simple pagination strategy when the paginator info is not requested https://github.com/nuwave/lighthouse/pull/2170
    Source code(tar.gz)
    Source code(zip)
  • v5.54.0(Jun 14, 2022)

  • v5.53.0(Jun 9, 2022)

Owner
NuWave Commerce
Web development and design firm based out of Arizona
NuWave Commerce
Syntax to query GraphQL through URL params, which grants a GraphQL API the capability to be cached on the server.

Field Query Syntax to query GraphQL through URL params, which grants a GraphQL API the capability to be cached on the server. Install Via Composer com

PoP 4 Jan 7, 2022
Monorepo of the PoP project, including: a server-side component model in PHP, a GraphQL server, a GraphQL API plugin for WordPress, and a website builder

PoP PoP is a monorepo containing several projects. The GraphQL API for WordPress plugin GraphQL API for WordPress is a forward-looking and powerful Gr

Leonardo Losoviz 265 Jan 7, 2023
Laravel wrapper for Facebook's GraphQL

Laravel GraphQL Use Facebook's GraphQL with Laravel 6.0+. It is based on the PHP port of GraphQL reference implementation. You can find more informati

Mikk Mihkel Nurges 1.9k Dec 31, 2022
šŸžšŸ§‘ā€šŸ³ An on-the-fly GraphQL Schema generator from Eloquent models for Laravel.

An on-the-fly GraphQL Schema generator from Eloquent models for Laravel. Installation Quickstart Model schemas Installation This package requires PHP

Scrn 100 Oct 16, 2022
GraphQL implementation with power of Laravel

Laravel GraphQL Use Facebook GraphQL with Laravel 5.2 >=. It is based on the PHP implementation here. You can find more information about GraphQL in t

Studionet 56 Mar 9, 2022
Create REST and GraphQL APIs, scaffold Jamstack webapps, stream changes in real-time.

API Platform is a next-generation web framework designed to easily create API-first projects without compromising extensibility and flexibility: Desig

API Platform 7.7k Jan 7, 2023
This bundle provides tools to build a complete GraphQL server in your Symfony App.

OverblogGraphQLBundle This Symfony bundle provides integration of GraphQL using webonyx/graphql-php and GraphQL Relay. It also supports: batching with

Webedia - Overblog 720 Dec 25, 2022
Pure PHP implementation of GraphQL Server ā€“ Symfony Bundle

Symfony GraphQl Bundle This is a bundle based on the pure PHP GraphQL Server implementation This bundle provides you with: Full compatibility with the

null 283 Dec 15, 2022
GraphQL Bundle for Symfony 2.

Symfony 2 GraphQl Bundle Use Facebook GraphQL with Symfony 2. This library port laravel-graphql. It is based on the PHP implementation here. Installat

Sergey Varibrus 35 Nov 17, 2022
EXPERIMENTAL plugin extending WPGraphQL to support querying (Gutenberg) Blocks as data, using Server Side Block registries to map Blocks to the GraphQL Schema.

WPGraphQL Block Editor This is an experimental plugin to work toward compatiblity between the WordPress Gutenberg Block Editor and WPGraphQL, based on

WPGraphQL 29 Nov 18, 2022
Test your PHP GraphQL server in style, with Pest!

Pest GraphQL Plugin Test your GraphQL API in style, with Pest! Installation Simply install through Composer! composer require --dev miniaturebase/pest

Minibase 14 Aug 9, 2022
Add Price Including tax for Magento's "cart" GraphQl query

Comwrap_GraphQlCartPrices Add Price Including tax for Magento's "cart" GraphQl query Query will looks like following: items { id __typenam

Comwrap 1 Dec 2, 2021
GraPHPinator āš” šŸŒ āš” Easy-to-use & Fast GraphQL server implementation for PHP

Easy-to-use & Fast GraphQL server implementation for modern PHP. Includes features from latest draft, middleware directives and modules with extra functionality.

Infinityloop.dev 34 Dec 14, 2022
A Statamic Pro addon that provides alternative GraphQL queries for collections, entries and global sets.

Statamic Enhanced GraphQL A Statamic CMS GraphQL Addon that provides alternative GraphQL queries for collections, entries and global sets. āš ļø This is

Grischa Erbe 2 Dec 7, 2021
Place where I record all knowledge gained for GraphQL from Laracasts & other tutorials.

Knowledge from Laracasts series: https://laracasts.com/series/graphql-with-laravel-and-vue What is GraphQL It is a query language for your API, and it

Nikola 0 Dec 26, 2021
Pure PHP realization of GraphQL protocol

Looking for Maintainers! Unfortunatelly, we cannot longer support this package and are looking for someone to take the ownership. Currently Only PRs w

null 714 Dec 21, 2022
A PHP port of GraphQL reference implementation

graphql-php This is a PHP implementation of the GraphQL specification based on the reference implementation in JavaScript. Installation Via composer:

Webonyx 4.4k Jan 7, 2023
The server component of API Platform: hypermedia and GraphQL APIs in minutes

API Platform Core API Platform Core is an easy to use and powerful system to create hypermedia-driven REST and GraphQL APIs. It is a component of the

API Platform 2.2k Dec 27, 2022
A PHP implementation of the GraphQL specification based on the JavaScript reference implementation

GraphQL This is a PHP implementation of the GraphQL specification based on the JavaScript reference implementation. Related projects DateTime scalar R

Digia 219 Nov 16, 2022