Download the PHP package xentral/laravel-api without Composer

On this page you can find all versions of the php package xentral/laravel-api. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package laravel-api

Laravel OpenApi

Latest Version on Packagist Total Downloads GitHub Actions

This package provides comprehensive tools for API specification, documentation, and implementation, enabling engineers to build a unified API experience.

Instead of managing YAML or JSON files, you can use strongly-typed PHP attributes to define your API endpoints and schemas directly alongside the responsible code. The provided attributes work seamlessly with the extended QueryBuilder from the spatie/laravel-query-builder package to provide a straightforward way of implementing your specified API endpoints.

There were six main goals in mind when creating this package:

Key Features

How does it work?

xentral/laravel-api is built upon the excellent zircote/swagger-php and spatie/laravel-query-builder packages, adding powerful features for Laravel applications.

The package enables you to manage multiple OpenAPI schema files within a single project. Default configuration is handled via the openapi.php config file.

The package provides opinionated and straightforward PHP 8 attributes to define OpenAPI specifications directly in your controller methods and request/resource classes. It includes a set of predefined attributes for common HTTP methods (GET, POST, PUT, PATCH, DELETE) that automatically:

These attributes extract the necessary information from your code structure, reducing duplication and keeping your API documentation in sync with your implementation.

Installation

Install the package via Composer:

The package will automatically register its service provider and be ready to use.

Usage

The following sections demonstrate how to define your API endpoints and schemas using PHP attributes.

Resource Definition

API resources are defined using the #[OA\Schema] attribute. This allows you to specify the properties of your resource, including their types and validation requirements. The example below demonstrates how to define a simple SalesOrder resource.

List Endpoints

You can define a list endpoint using the #[ListEndpoint] attribute. This allows you to specify the path, resource class, description, and any additional parameters such as filters, sorts, and includes. The example below shows how to define a list endpoint for sales orders.

Includes

The includes argument lists the relations a client may request with ?include=. A plain entry is open to every caller of the endpoint. A string key names an include that requires a token scope; its value is that scope, or a list of scopes when the include needs all of them:

Every name still lands in the enum of the include parameter. A scoped include additionally renders one sentence per gated include into the parameter's description and the scopes into an x-include-scopes extension, so tooling can read the gate without parsing the text:

The attribute only documents the scope. Enforcing it at runtime is the application's job, for example where it registers its allowed includes.

Filtering

This package leverages the spatie/laravel-query-builder package to provide an intuitive filter implementation. However, the filters are adapted to follow our own conventions. Each filter in the URL always contains key, op, and value parameters. Here are some examples:

A rejected filter answers with a validation error keyed on the key the client sent, even when the key reads another column (documentNumber on belegnr) or a relation. A filter class built directly, outside the QueryFilter factories, only knows its column unless it is given the public name as well.

Unset values and relations

A text column is unset when it holds NULL or '', and the equality, set and containment operators read both alike: a NULL row matches exactly when '' would. So isNull matches both, notEquals 'x' keeps both, and notEquals '' drops both. The comparisons such as lessThan never match a NULL row. Number and date filters keep NULL rows under notEquals.

A dotted key such as lineItems.number filters through a relation, and each condition is checked against the related rows on its own, so two conditions can be met by different rows:

Operator A parent matches when
equals, in, contains, startsWith, endsWith, comparisons, isNotNull some related row matches
notEquals, notIn, notContains no related row matches the positive operator
isNull no related row carries a value

A parent without related rows therefore matches the negations and isNull, and nothing else. On a text or id key, equals with several values needs a matching related row for each value.

Boolean filter groups

Several filters in the list above are combined with and. To express A or B instead, send a single group object with an explicit operator rather than the flat list — either as a deepObject or, as below, JSON encoded:

An and group is just the flat list spelled out and works everywhere. An or group changes how the query is built, so an endpoint has to opt in on both layers:

except names the filters that may not appear inside an or group: a filter lifting a global scope switches the whole query rather than one branch, and a filter whose meaning pairs several keys is not self-contained. An or group on an endpoint without the opt-in and an excluded filter inside one are rejected as validation errors.

A condition may itself be a group, so a mixed expression such as (A and B) or (C and D) is a single request:

Groups nest to at most QueryBuilderRequest::MAX_GROUP_DEPTH (5) levels, the outermost group counting as level one; anything deeper is a validation error. Nesting rides on the same opt-in whatever the operators are — a group holding a sub-group on an endpoint that never called allowOrFilterGroups() is rejected even when every operator is and, so an endpoint that did not opt in keeps exactly the contract it had.

An excluded filter stays usable as a direct condition of a top-level and group, and in the flat list. Those are the only positions applied on the outer builder; inside a sub-group the query runs in a closure, where lifting a global scope silently does nothing, so an excluded key below the top level is rejected rather than quietly ignored.

On the spec side an opted-in endpoint also names its component schemas:

That emits SalesOrderFilterCondition plus one group component per nesting level into components/schemas — SalesOrderFilterGroup for the top level, SalesOrderFilterGroupDepth2 down to SalesOrderFilterGroupDepth5 below it — and points the parameter at the top level. Each level's conditions refer to the condition schema and to the next level only, and the deepest level accepts conditions alone, so the schema bounds the depth structurally and never refers to itself. The chain is unrolled on purpose: a self-referencing $ref describes the wire format in one line, but tooling that dereferences a spec into a plain object tree cannot serialise the cycle. The runtime enforces the same cap from the same constant.

Filter defaults for keys the request does not name stay outside the group, as does search — both keep narrowing the whole result set. A key named anywhere in the tree, at any depth, counts as named and keeps its default from being applied.

Truthy integer flags

QueryFilter::booleanInteger() filters a legacy integer column that is semantically boolean, and QueryFilter::boolean() uses the same filter. It matches by truthiness, not by an exact 1, because consumers expose such a column as (bool) $row->column:

Filter SQL on a column
equals true, notEquals false column > 0
equals false, notEquals true (column = 0 or column is null)

false deliberately matches NULL. A NULL is rendered as false in the payload, so a filter skipping those rows would contradict what the API returns for them.

On a dotted key the two spellings of a row part ways, as in the relation table above: equals false needs some related row to be falsy, while notEquals true needs no related row to be truthy, so a parent without related rows matches only the negation.

Accepted values are true, 1, '1', 'true' and false, 0, '0', 'false'; anything else is a validation error. Only equals and notEquals are supported.

A negative value matches neither side, even though PHP would cast it to true - the filter exists for columns holding 0, 1 or NULL. Use QueryFilter::number() if a column carries real quantities.

Id filters on relations and expressions

QueryFilter::identifier() resolves to a column. When the target is a computed predicate instead - a pivot relation, or a legacy column that stores the id inside another value - use QueryFilter::identifierCallback() and hand it that predicate:

The callback does one thing: constrain the query to rows matching any of the ids it receives. Everything else is owned by the filter:

Pair it with the IdFilter spec attribute passing operators: FilterOperator::MEMBERSHIP, so the spec documents exactly the four operators the callback accepts (the IdFilter default also covers isNull/isNotNull, which a callback filter does not support).

Reusing the filter value coercion

Filters that build their own predicate - a relation based boolean filter using whereHas/whereDoesntHave, for instance - should not re-implement the accepted value spellings. FilterValue exposes the coercion the packaged filters use:

Both throw a ValidationException carrying the messages documented above, so a hand-written filter stays consistent with the packaged ones. The second argument keys that exception, so pass the API facing filter name - not the $property a filter receives, which is the internal column name when one is mapped. The packaged filters take the name for exactly this reason, as in QueryFilter::booleanInteger('isVariant', 'variante'), which reports errors under isVariant.

Pagination

This package provides flexible pagination options that can be configured per endpoint. You can choose from three different pagination types, each optimized for different use cases:

Pagination Types

Simple Pagination (PaginationType::SIMPLE)

Table Pagination (PaginationType::TABLE)

Cursor Pagination (PaginationType::CURSOR)

Dynamic Pagination Control

For endpoints that support multiple pagination types, clients can control the pagination format using the x-pagination header:

Pagination Parameters

Different pagination types use different query parameters:

Simple & Table Pagination:

Cursor Pagination:

Configurable Response Format

You can configure whether pagination fields use snake_case or camelCase in your configuration:

View Endpoints

View endpoints are defined using the #[GetEndpoint] attribute. This allows you to specify the path, resource class, description, and additional parameters such as includes. The example below demonstrates how to define a view endpoint for retrieving a single sales order.

Defining Request Bodies

Request bodies are defined similarly to resources, using the #[OA\Schema] attribute. This is applied to Laravel's Form Request classes (or other data objects like spatie/laravel-data). This allows you to specify the properties of your request body, including their types and validation requirements. The example below demonstrates how to define a request body for creating a sales order.

Unlike resources, request schemas stay open — do not set additionalProperties: false on them. A request payload is mapped onto the properties the endpoint declares, so a property that is not declared is never read: it is not stored and it does not raise an error. additionalProperties: false would promise a rejection that never happens. On a response schema it is a real promise about the shape we return, so keep it there.

Create Endpoints

Create endpoints are defined using the #[PostEndpoint] attribute. This allows you to specify the path, resource class, description, and additional parameters such as request body and response. The successStatus parameter allows you to specify a different success status code (default is 200). The example below demonstrates how to define a create endpoint for a sales order.

Update Endpoints

Update endpoints are defined using either the #[PutEndpoint] or #[PatchEndpoint] attribute. These work identically to the #[PostEndpoint] attribute, allowing you to specify the path, resource class, description, and additional parameters such as request body and response. The example below demonstrates how to define an update endpoint for a sales order.

Delete Endpoints

Delete endpoints are defined using the #[DeleteEndpoint] attribute. This allows you to specify the path, description, and additional parameters such as custom validation messages. The example below demonstrates how to define a delete endpoint for a sales order with custom validation to ensure that only pending sales orders can be deleted. When a sales order is not in a pending state, a validation exception is thrown with a descriptive message.

Generating OpenAPI Schema

Once you have defined your endpoints and schemas, generate the OpenAPI specification file:

Configuration

After installation, you can publish the configuration file using:

This will create a config/openapi.php file with the following options:

Multiple Schemas

You can define multiple schemas in the configuration file. Each schema can have its own settings, including which folders to scan, output file, and other OpenAPI information.

To generate a specific schema, you can pass the schema name to the openapi:generate command:

Web Interface

The package includes a built-in web interface for viewing and interacting with your OpenAPI documentation. By default, it's available at /api-docs and is protected by the web and auth middleware.

You can configure the web interface in the docs section of the configuration file:

API Documentation Clients

The package supports two different API documentation clients for rendering your OpenAPI documentation:

Swagger UI (Default)

Scalar

Client Configuration

You can configure which client to use at three different levels:

Global Configuration (Environment)

Global Configuration (Config)

Per-Schema Configuration

Runtime Override (Query Parameter)

The configuration precedence is: Query Parameter > Per-Schema > Global > Default (swagger).

Accessing Different API Versions

If you have multiple schemas configured, you can access their documentation at:

Reusing Filters

Reusing filters across multiple endpoints improves consistency and reduces duplication. This is achieved by creating a custom Attribute class that implements the FilterSpecCollection interface. Here's an example:

Once defined, you can use this custom filter collection in your controller methods:

Testing

Use the package xentral/laravel-testing to validate your API requests and responses against the OpenAPI schemas defined in your tests.

Advanced Configuration

Schema Configuration Options

Web Interface Configuration

Best Practices

Organizing Your API

  1. Use consistent naming: Keep your resource names consistent across endpoints, schemas, and tags
  2. Group related endpoints: Use tags to group related endpoints together
  3. Document all parameters: Always provide descriptions for filters, includes, and other parameters
  4. Use feature flags: Mark experimental endpoints with feature flags for better API governance

Schema Design

  1. Keep schemas focused: Each schema should represent a single concept
  2. Use references: Leverage $ref to reuse common schemas and avoid duplication
  3. Mark required fields: Always specify which fields are required in your schemas
  4. Use appropriate types: Use the most specific OpenAPI type for each field

Pagination Guidelines

  1. Choose the right pagination type:
    • Use Simple for basic list views and mobile APIs where performance is critical
    • Use Table for admin interfaces and dashboards where users need page numbers and totals
    • Use Cursor for real-time feeds, activity streams, and very large datasets
  2. Support multiple types: For flexible APIs, support multiple pagination types and let clients choose
  3. Consider your audience: Internal tools may prefer table pagination, while public APIs often benefit from simple or cursor pagination
  4. Use appropriate defaults: Set sensible defaultPageSize and maxPageSize values for your use case

Performance Considerations

  1. Limit includes: Be selective about which relationships can be included to avoid N+1 queries
  2. Set reasonable pagination limits: Use maxPageSize to prevent excessive data loading
  3. Use caching: Consider caching generated OpenAPI files in production
  4. Choose efficient pagination: Cursor pagination performs better on large datasets than offset-based pagination

Troubleshooting

Common Issues

Schema Generation Fails

Validation Errors

Missing Endpoints in Documentation

Performance Issues

Getting Help

If you encounter issues:

  1. Review the generated OpenAPI file for syntax errors or missing definitions
  2. Enable Laravel's debug mode to see detailed error messages
  3. Examine the package's test suite for example usage patterns
  4. Search the GitHub issue tracker for similar problems and solutions
  5. Check that your PHP and Laravel versions meet the package requirements

Contributing

Roadmap

Future development ideas include:

Please see CONTRIBUTING for details.

Security

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.


All versions of laravel-api with dependencies

PHP Build Version
Package Version
Requires php Version ^8.3
illuminate/console Version ^12.0
illuminate/http Version ^12.0
illuminate/support Version ^12.0
illuminate/validation Version ^12.0
spatie/laravel-data Version ^4.17
spatie/laravel-query-builder Version ^6.3
swagger-api/swagger-ui Version ^5.21
zircote/swagger-php Version ^5.3
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package xentral/laravel-api contains the following files

Loading the files please wait ...