Giter Site home page Giter Site logo

overblog / dataloader-bundle Goto Github PK

View Code? Open in Web Editor NEW
45.0 9.0 14.0 66 KB

This bundle allows to easy use DataLoaderPHP in your Symfony project through configuration.

License: MIT License

PHP 100.00%
dataloader symfony-bundle bundle php graphql symfony

dataloader-bundle's Introduction

DataLoaderBundle

This bundle allows to easy use DataLoaderPHP in your Symfony project by configuring it through configuration.

Build Status Coverage Status Latest Stable Version License

Requirements

This library requires PHP >= 5.5 to work.

Installation

Download the Bundle

composer require overblog/dataloader-bundle

Enable the Bundle

class AppKernel extends Kernel
{
    public function registerBundles()
    {
        $bundles = [
            // ...

            new Overblog\DataLoaderBundle\OverblogDataLoaderBundle(),
        ];

        // ...
    }

    // ...
}

Getting Started

Here a fast example of how you can use the bundle

overblog_dataloader:
    defaults:
        # required
        promise_adapter: "overblog_dataloader.react_promise_adapter"
        # optional
        factory: ~
        options:
            batch: true
            cache: true
            max_batch_size: ~
            cache_map: "overblog_dataloader.cache_map"
            cache_key_fn: ~
    loaders:
        users:
            alias: "users_dataloader"
            batch_load_fn: "@app.user:getUsers"
        posts: 
            batch_load_fn: "Post::getPosts"
            options:
                max_batch_size: 15
                batch: false
                cache: false
                cache_map: "app.cache.map"
                cache_key_fn: "@app.cache"
        images:
            factory: my_factory
            batch_load_fn: "Image\\Loader::get"

This example will create 3 loaders as services:

  • "@overblog_dataloader.users_loader" with alias "@users_dataloader"
  • "@overblog_dataloader.posts_loader"
  • "@overblog_dataloader.images_loader" create using custom factory function "my_factory"

Here the list of existing promise adapters:

Combine with GraphQLBundle

This bundle can be use with GraphQLBundle. Here an example:

  • Bundle config
#graphql
overblog_graphql:
    definitions:
        schema:
            query: Query
    services:
        promise_adapter: "webonyx_graphql.sync_promise_adapter"

#dataloader
overblog_dataloader:
    defaults:
        promise_adapter: "overblog_dataloader.webonyx_graphql_sync_promise_adapter"
    loaders:
        ships:
            alias: "ships_loader"
            batch_load_fn: "@app.graph.ships_loader:all"
  • Batch loader function
services:
    app.graph.ship_repository:
        class: AppBundle\Entity\Repository\ShipRepository
        factory: ["@doctrine.orm.entity_manager", getRepository]
        arguments:
            - AppBundle\Entity\Ship

    app.graph.ships_loader:
        class: AppBundle\GraphQL\Loader\ShipLoader
        arguments:
            - "@overblog_graphql.promise_adapter"
            - "@app.graph.ship_repository"
<?php

namespace AppBundle\GraphQL\Loader;

use AppBundle\Entity\Repository\ShipRepository;
use GraphQL\Executor\Promise\PromiseAdapter;

class ShipLoader
{
    private $promiseAdapter;

    private $repository;

    public function __construct(PromiseAdapter $promiseAdapter, ShipRepository $repository)
    {
        $this->promiseAdapter = $promiseAdapter;
        $this->repository = $repository;
    }

    public function all(array $shipsIDs)
    {
        $qb = $this->repository->createQueryBuilder('s');
        $qb->add('where', $qb->expr()->in('s.id', ':ids'));
        $qb->setParameter('ids', $shipsIDs);
        $ships = $qb->getQuery()->getResult();

        return $this->promiseAdapter->all($ships);
    }
}
  • Usage in a resolver
    public function resolveShip($shipID)
    {
        $promise = $this->container->get('ships_loader')->load($shipID);

        return $promise;
    }

This is an example using the sync promise adapter of Webonyx.

License

Overblog/DataLoaderBundle is released under the MIT license.

dataloader-bundle's People

Contributors

adri avatar benmorel avatar gordinskiy avatar ivoba avatar jerowork avatar liinkiing avatar mcg-web avatar renatomefi avatar rpander93 avatar ruudk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dataloader-bundle's Issues

CacheMap shared between all DataLoaders

Hi,

Could you please elaborate why the CacheMap is shared between all DataLoaders by default? This gave me all kinds of weird results whereby the promises of different entities were shared. For example, the following query would work if I either included the productType or location field, but not with both.

query {
  products {
    id
    productType {
      id
      description    
    }
    location {
      id
      name
    }
  }
}

I traced the error by inserting a few lines at https://github.com/overblog/dataloader-php/blob/master/src/DataLoader.php#L66 echo'ing $cacheKey and the $batchLoadFn (as a string) which showed me that the promise of productType would be returned for a location with the same id.

Manually overwriting the service definition as

services:
  overblog_dataloader.cache_map:
    public: false
    shared: false
    class: Overblog\DataLoader\CacheMap

solved all my problems and gave me the expected results. Is this a bug or am I doing something wrong?

Global batch load function

The batch load functions and classes look pretty much always the same so I'd like to get rid of them in favor of some global batch function that would receive the name of the data loader and the ids and would return a promise just like normal batch_load_fn. Currently I hacked it using __call but it's not ideal.

Make it easier to register dataloaders from PHP (autowire autoconfigure)

Currently, it seems only possible to create data loaders dynamically with the bundle's configuration.

But that registers dynamic services that you need to inject in your resolvers.

If you use autowire, that becomes a pain.

What if you can just create a dataloader with PHP, and that this bundle automatically finds it and registers it?

Symfony 5.0 support

We have restriction to Symony 3 | 4 in composer.json. What's necessary to allow Symfony 5.0 support?

DataLoader destroyed before promise complete.

I've managed to hit DataLoader destroyed before promise complete. in this file.

Since I'm using the bundle it's not explicitly clear how I got to a broken state.

It's likewise hard to create a minimal test case.

Any clues why this might happen?

More elaborate example

Hi,

I'm a bit in the dark on how to implement this in my schema. I'm using the GraphQLBundle. In my schema, I have a query field named "contracts" which returns an array of contract entities. Each contract contains a one-to-many to an entity named "location". How would I implement this?

In my ContractsResolver class, I'd like to return a promise from my ContractLoader which returns an array of contracts. Then, the locations field on each contract should also return a promise resolving to an array of locations. How should I implement this in my resolvers and scheme?

What is the point of this bundle

  1. The following does not require this bundle, except the adapter, which purpose is neither explained nor obvious from readme:
services:
    app.graph.ship_repository:
        class: AppBundle\Entity\Repository\ShipRepository
        factory: ["@doctrine.orm.entity_manager", getRepository]
        arguments:
            - AppBundle\Entity\Ship

    app.graph.ships_loader:
        class: AppBundle\GraphQL\Loader\ShipLoader
        arguments:
            - "@overblog_graphql.promise_adapter"
            - "@app.graph.ship_repository"
  1. Why do I need to define the adapter in another bundle:
#graphql
overblog_graphql:
    definitions:
        schema:
            query: Query
    services:
        promise_adapter: "webonyx_graphql.sync_promise_adapter"
#dataloader
overblog_dataloader:
    defaults:
        promise_adapter: "overblog_dataloader.webonyx_graphql_sync_promise_adapter"
    loaders:
        ships:
            alias: "ships_loader"
            batch_load_fn: "@app.graph.ships_loader:all"

Again, what is the purpose of the adapter? I create service, to create a service which lets the adapter call a load_fn, but it seems from the following example, that I still have to somehow collect the IDs:

    public function resolveShip($shipsID)
    {
        $promise = $this->container->get('ships_loader')->load($shipsID);

        return $promise;
    }

So I could simply spare a lot of config and simply use the deffered from webonyx and collect my ids anyway. I could create a single service (instead of two) with almost zero config (using autoconfig/autowire) which does exactly this. Also the resolver usage does magically get shipIds, while actually the resolver would not get IDs, but the value/data being resolved.

The resolver usage combined with previous explanation feels like an "1. do this 2. ??? 3. profit?" currently ;(.

Docs are a bit confusing re: load / all

Hi there, I'm trying to get up to speed on GraphQL and I think either the example in the README is wrong, or else maybe could just use some clarification for n00bs such as myself.

Specifically, the "Usage in a resolver" seems to be calling the "load" function of ShipLoader, but of course ShipLoader does not have a "load" function, only an "all" function.

Is there supposed to be an intermediate object, or some functions added via inheritance?

Allow to add a null value in the list of keys

Hello,

I'm using your excellent GraphQL bundle and so the dataloader.

In one of my type, I need to load another type using the dataloader. To do that, I use a property of my first type, but this property can be null sometimes. Of course, the result for this key would be null and this is what I'm looking for. But now, this throws an error because of the checkKey method of overblog/dataloader-php/src/DataLoader.php

Thank you a lot
Jourdan

New version?

Hi, thank you for the really nice library.
I wanted to ask whether you planning to release a new version with the fixes in main branch. It would be awesome as it fixes compatibility with PHP 8.1.

If anything has to be done before, I'm happy to help.

Add support for namespaced service names

Service ids with \ are not considered viable services. Since symfony 3.4+ recommends and auto configuring services as their FQCN, you need to introduce an alias to configure batch_load_fn.

To fix this, the Overblog\DataLoaderBundle\DependencyInjection\Configuration::SERVICE_CALLABLE_NOTATION_REGEX should be changed. We could use the same capture group definition as for function in PHP_CALLABLE_NOTATION_REGEX, i guess.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.