Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"smallest working example using no framework" doesn't work #553

Closed
shish opened this issue Feb 3, 2023 · 15 comments
Closed

"smallest working example using no framework" doesn't work #553

shish opened this issue Feb 3, 2023 · 15 comments
Labels
documentation Related to errors, omissions and improvements to docs

Comments

@shish
Copy link
Contributor

shish commented Feb 3, 2023

// $cache is a PSR-16 compatible cache.
// $container is a PSR-11 compatible container.
$factory = new SchemaFactory($cache, $container);

$cache and $container aren't defined anywhere in the example code :(

I've created an empty in-memory cache object to be used as $cache, and an empty container object to be used as $container, and then my schema comes out empty.

I'm guessing that somehow I'm supposed to be supplying a $container that is pre-populated full of Types? (Does addTypeNamespace not automatically load all the types from the namespace?)

@oojacoboo
Copy link
Collaborator

Good question. The service container is certainly used for instantiation of various services/classes. Your types, operations and factories should be callable through your container. So yes, "pre-populated", if you'd like to say it like that. Although most containers don't actually "pre-populate", but instead handle instantiation and caching. If they weren't called in this fashion, you wouldn't be able to make use of your container service.

@oojacoboo oojacoboo added the documentation Related to errors, omissions and improvements to docs label Feb 4, 2023
@shish
Copy link
Contributor Author

shish commented Feb 4, 2023

So I'm trying to reverse-engineer graphqlite's expectations by providing a PSR-11 compatible container which just logs calls:

class C implements ContainerInterface
{
    public function get(string $id): mixed {
        echo("get($id)\n");
    }
    public function has(string $id): bool {
        echo("has($id)\n");
        return false;
    }
}

... but apparently it never gets called at all?

Then I wonder if I'm doing something wrong somewhere else:

<?php

namespace Shimmie2;

require_once("vendor/autoload.php");

use TheCodingMachine\GraphQLite\SchemaFactory;
use TheCodingMachine\GraphQLite\Annotations\Type;
use TheCodingMachine\GraphQLite\Annotations\Field;
use TheCodingMachine\GraphQLite\Annotations\Query;
use TheCodingMachine\GraphQLite\Annotations\Mutation;
use GraphQL\Utils\SchemaPrinter;

#[Type]
class TagUsage
{
    #[Field]
    public string $tag;
    #[Field]
    public int $uses;

    /**
     * @return TagUsage[]
     */
    #[Query]
    public static function tags(string $search, int $limit=10): array {
        return []; // get from database
    }
}

class C implements \Psr\Container\ContainerInterface
{
    public function get(string $id): mixed {
        echo("get($id)\n");
    }
    public function has(string $id): bool {
        echo("has($id)\n");
        return false;
    }
}

$cache = new \Sabre\Cache\Memory();
$container = new C();
$factory = new SchemaFactory($cache, $container);
$factory->addControllerNamespace('Shimmie2\\')
        ->addTypeNamespace('Shimmie2\\');
$factory->devMode(); // vs prodMode
$schema = $factory->createSchema();
echo(SchemaPrinter::doPrint($schema));
$ php test.php
type Mutation {
  """
  A placeholder query used by thecodingmachine/graphqlite when there are no declared mutations.
  """
  dummyMutation: String
}

type Query {
  """
  A placeholder query used by thecodingmachine/graphqlite when there are no declared queries.
  """
  dummyQuery: String
}

@oojacoboo
Copy link
Collaborator

It seems like it's not recognizing your Query attribute, probably since it's defined on a Type. Try adding that to a different class. And yea, it's possible that since there aren't any defined operations the container never gets called?

@shish
Copy link
Contributor Author

shish commented Feb 5, 2023

Tried putting my query in a separate class, even a separate class in a separate namespace (so that addControllerNamespace and addTypeNamespace are separate), no luck :(

@oojacoboo
Copy link
Collaborator

Have you tried the namespace without the trailing \? The error makes it clear that there isn't any defined mutations or queries. So, it's not finding them being defined in the controller namespace.

@shish
Copy link
Contributor Author

shish commented Feb 8, 2023

Tried without the trailing slash, still doesn't work

@oojacoboo
Copy link
Collaborator

@shish It's worth mentioning that the container is also used for AutoWire.

https://graphqlite.thecodingmachine.io/docs/annotations-reference#autowire

@shish
Copy link
Contributor Author

shish commented Mar 7, 2023

Dropping a note for anybody who stumbles across this thread in the future - I never did figure out how to use graphqlite without a framework, I ended up building my own system from scratch instead - that is very much a minimalist stop-gap though, I'd still rather use the full-featured graphqlite if anybody figures out how ^^;;

@oojacoboo
Copy link
Collaborator

@shish We use GraphQLite with our custom "framework", if you want to call it a framework. It's really just a custom application with it's own bootstrapping, request and error handling, and more. I'm not entirely sure what issues you're running into. You've been discussing things at a rather macro level.

@shish
Copy link
Contributor Author

shish commented Mar 7, 2023

I'm literally copy-pasting the "smallest working example using no framework" code into a file called test.php and running php test.php, then trying to fix the issues I run into (some variables aren't defined, and when I define them according to the standards documents referenced in the comments, my output is empty - my attempt to make things work is the code above)

A step-by-step walkthrough of my process from "blank folder" to "try creating a new minimal project according to the minimal-working-example guide" to "running into problems":

$ mkdir example
$ cd example
$ composer require thecodingmachine/graphqlite
$ composer require sabre/cache
$ cat > test.php
<?php

namespace Shimmie2;

require_once("vendor/autoload.php");

use TheCodingMachine\GraphQLite\SchemaFactory;
use TheCodingMachine\GraphQLite\Annotations\Type;
use TheCodingMachine\GraphQLite\Annotations\Field;
use TheCodingMachine\GraphQLite\Annotations\Query;
use TheCodingMachine\GraphQLite\Annotations\Mutation;
use GraphQL\Utils\SchemaPrinter;

#[Type]
class TagUsage
{
    #[Field]
    public string $tag;
    #[Field]
    public int $uses;

    /**
     * @return TagUsage[]
     */
    #[Query]
    public static function tags(string $search, int $limit=10): array {
        return []; // get from database
    }
}

class C implements \Psr\Container\ContainerInterface
{
    public function get(string $id): mixed {
        echo("get($id)\n");
    }
    public function has(string $id): bool {
        echo("has($id)\n");
        return false;
    }
}

$cache = new \Sabre\Cache\Memory();
$container = new C();
$factory = new SchemaFactory($cache, $container);
$factory->addControllerNamespace('Shimmie2\\')
        ->addTypeNamespace('Shimmie2\\');
$factory->devMode(); // vs prodMode
$schema = $factory->createSchema();
echo(SchemaPrinter::doPrint($schema));
^D
$ php test.php
type Mutation {
  """
  A placeholder query used by thecodingmachine/graphqlite when there are no declared mutations.
  """
  dummyMutation: String
}

type Query {
  """
  A placeholder query used by thecodingmachine/graphqlite when there are no declared queries.
  """
  dummyQuery: String
}

It looks like there's now some extra examples at the bottom of the no-framework guide, so maybe something in there will give clues as to what I'm missing ^^

@oojacoboo
Copy link
Collaborator

oojacoboo commented Mar 9, 2023

What's the error you're getting? You say the output is empty. Can you query the __schema?

It'd be great to get the docs updated on this if you can document the changes and submit a PR upon getting a minimal version running.

@shish
Copy link
Contributor Author

shish commented Mar 9, 2023

When I say the output is empty I mean there are no mutations or queries, just "A placeholder query used by thecodingmachine/graphqlite when there are no declared queries.", even though I have attached #[Query] to a function within the namespace specified by $factory->addControllerNamespace() -- there's no error message, just a lack of output (see the output of running test.php at the bottom )

@oojacoboo
Copy link
Collaborator

oojacoboo commented Mar 9, 2023

Okay, played around with your script.

You need to add your classes to the autoloader in your composer.json.

composer --autoload

Which means you need to re-organize your files a bit. GraphQLite is looking in the autoload for the mentioned namespaces.

{
    "require": {
        "thecodingmachine/graphqlite": "^6.1",
        "sabre/cache": "^2.0"
    },

    "autoload": {
        "psr-4": {
            "Shimmie2\\": "src/"
        }
    }
}

Put your controller/type in the src dir in another file.

composer dump-autoload

Again, a PR update on this would be welcomed.

@shish
Copy link
Contributor Author

shish commented Mar 13, 2023

Aha, that is a hugely useful hint, now I at least know where to start looking, thank you :D

Alas, I'm working on adding graphql support to an application that predates psr-4 by around 10 years, and has its whole own module loading stuff...

Maybe as well as updating the docs to include a complete working end-to-end example, I can also submit a PR to allow it to load from existing in-memory classes instead of assuming the presence of an autoloader? 👀

@oojacoboo
Copy link
Collaborator

oojacoboo commented Mar 13, 2023

Composer has support for pre PSR-4 autoloading - check the docs.

A PR would be great on the minimal example and docs - maybe including a bit on Composer autoload requirements. There isn't any need to mention pre PSR-4 autoloading. Few people are doing that these days and most have already moved their autoloading to Composer anyway.

For reference, we used to handle autoloading outside Composer and migrated it all to Composer. We even have some non-PSR-4 autoloading in our Composer config - still.

shish added a commit to shish/graphqlite that referenced this issue Mar 14, 2024
…ne#553

This example had implicit-and-undocumented dependencies on composer.json, and explicit-but-unexplained dependencies on "a container" and "a cache", leaving the installation and configuring of these as an exercise to the reader. I have changed it so that the example code can be copy-pasted verbatim, and the user will end up with an example which runs, which I find much easier to learn from :)

I'm still not actually sure if I'm doing this correctly, because thecodingmachine#553 mentioned loading classes via the PSR-4 autoloader, and I found that it only worked when I manually listed out my controller classes inside the PSR-11 container, but it works...
shish added a commit to shish/graphqlite that referenced this issue Mar 20, 2024
…ne#553

This example had implicit-and-undocumented dependencies on composer.json, and explicit-but-unexplained dependencies on "a container" and "a cache", leaving the installation and configuring of these as an exercise to the reader. I have changed it so that the example code can be copy-pasted verbatim, and the user will end up with an example which runs, which I find much easier to learn from :)

I'm still not actually sure if I'm doing this correctly, because thecodingmachine#553 mentioned loading classes via the PSR-4 autoloader, and I found that it only worked when I manually listed out my controller classes inside the PSR-11 container, but it works...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Related to errors, omissions and improvements to docs
Projects
None yet
Development

No branches or pull requests

2 participants