Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Api Images Laravel Package

youshido/api-images

A Laravel package for managing images in API-driven applications. It provides upload and storage helpers, configurable image transformations, and model attachments so you can serve consistent image assets through your API without custom boilerplate.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install alongside the core GraphQL library. The package is an extension for youshido/graphql, not a standalone uploader:

    composer require youshido/api-images
    

    You will already need youshido/graphql in the project (it is a transitive requirement, but pin it explicitly so a future api-images release doesn't drag an incompatible major).

  2. Look at the source before the README. With 4 stars and 0 dependents, treat the src/ directory as the canonical documentation. The entry points you care about are the image/upload GraphQL type, the scalar that parses incoming files, and any storage/resolver class. Read those three first; the README on such packages is usually a stub.

  3. Register the type in your schema. Add the image type and the upload scalar to your Schema config (the exact class names come from src/). A minimal schema that exposes an upload looks conceptually like:

    // config/schema.php (youshido/graphql style)
    return [
        'types' => [
            MyApp\GraphQL\Types\ImageType::class,
        ],
        'query' => MyApp\GraphQL\QueryType::class,
        'mutation' => MyApp\GraphQL\MutationType::class,
    ];
    
  4. First use case to prove it works: a single uploadImage(input: ImageInput!): Image mutation that accepts a multipart upload, writes the file to storage/app/public, and returns the resulting URL. Wire that end-to-end (client → GraphQL → disk → response) before building anything on top of it. Because the package sits between the GraphQL parser and your filesystem, the most common failure is at that boundary, and you want to have confirmed it once manually.

  5. Publish/verify any config. If the package ships a config file, publish it and diff it against your application config so you know where the storage disk, path prefix, and size limits are set.

Implementation Patterns

  • Treat it as a GraphQL type + scalar layer, not a file manager. The package's job is to accept a file through the GraphQL layer and hand you something usable. Persistence, naming, and thumbnailing are your responsibility (Laravel's Storage facade, Intervention\Image, or spatie/laravel-medialibrary fit naturally underneath it).

  • Isolate the upload mutation. Keep the resolver thin: validate the scalar's output, move the file to a disk, then delegate to an application service. That way if you later swap youshido/api-images for laravel-medialibrary's GraphQL or a custom upload scalar, only the resolver changes.

  • Wrap the resolver in a service. Example pattern:

    class UploadImageResolver
    {
        public function __construct(private ImageService $images) {}
    
        public function resolve($root, array $args): array
        {
            $file = $this->images->fromUploadedFile($args['input']['file']);
            return [
                'id'    => $file->id,
                'url'   => $file->url(),
                'width'  => $file->width(),
                'height' => $file->height(),
            ];
        }
    }
    
  • Use the returned type as your contract. Whatever shape the package's image type exposes (url, width, height, mime), lean on that as the API contract returned to clients. Add your own wrapper field if you need metadata the package doesn't expose, rather than monkey-patching its type.

  • Integrate with Laravel's validation by validating before the scalar sees the file. GraphQL's multipart spec is loose about file validation; do MIME/size checks in a FormRequest-equivalent or a validation service in the resolver. Don't expect the package to enforce your size limits.

  • Pattern for multi-image fields: build an [Image!]! list input and have your resolver loop over files. The package generally handles one upload per field; batch handling is application-level logic.

  • In tests, resolve the mutation with UploadedFile instances built via UploadedFile::fake() (or Symfony's UploadedFile) and assert the file lands on the configured disk. Do not test the package's internals — test that your mutation returns the expected image shape.

  • Integration tip: pair it with youshido/graphql's relay/type-loader so the image type can be referenced from other types without circular schema definitions. Register it once in the schema config and reference by class name everywhere else.

Gotchas and Tips

  • Maintenance risk is the headline. 4 stars, 0 dependents, and a score of 0.08 mean you are one of the few people running this in production. Pin the version, fork it internally if you depend on it, and have a migration path in mind (a ~200-line custom upload scalar in youshido/graphql is a viable replacement).

  • Version alignment with youshido/graphql is fragile. The package was written against a specific era of youshido/graphql (likely the 1.x line). Check composer.json of both, and install with --prefer-lowest once to confirm compatibility with your pinned core version. Upgrading either independently can break the scalar's parse method.

  • Multipart file uploads through GraphQL are not native. The GraphQL spec is JSON; multipart upload is a community convention (graphql-multipart-request-spec). Confirm your HTTP client (Apollo, Relay, urql) uses the same operations / map / 0 field naming that the package expects. Mismatched multipart conventions produce silent "file is null" errors with no exception.

  • Check how the scalar exposes the file. Some versions hand you a UploadedFile / SplFileInfo; others pass a Psr\Http\Message\UploadedFileInterface or an array. Dump the scalar's parseValue()/parseLiteral() output during debugging — this is the #1 source of confusion.

  • Storage disk matters. The package may default to public or to an absolute path from its config. If your app serves files via storage:link, verify the returned URL points to the symlinked location, not a raw filesystem path.

  • No CSRF, no auth, no throttling. The package is a serializer, not a security layer. Add auth middleware on the mutation, rate-limit uploads at the HTTP layer, and never trust the client's claimed filename or MIME.

  • Debugging tactic: log the raw multipart request body (Laravel's \Illuminate\Http\Request::all()) before GraphQL parses it. If the file isn't in the request, the problem is upstream of the package; if it is but the scalar returns null, the problem is in the package's parsing and you should read src/ directly.

  • Extension points are limited. The type and scalar are the surfaces you can extend (subclass the type to add fields). Don't try to swap the storage backend unless the package exposes a setter or config for it — otherwise write your own resolver and skip the package's storage entirely.

  • Fork-readiness checklist. Before committing: (1) is src/ under ~500 lines? (2) are there tests? (3) what's the last commit date? If the answers are "no", "no", "years ago", write a small custom upload scalar using youshido/graphql's ScalarTypeInterface — you'll spend an afternoon and own it.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource