2 |
3 | # API Platform Documentation
4 |
5 | [](https://github.com/api-platform/docs/actions/workflows/ci.yml)
6 |
7 | Welcome to the official documentation for [API Platform](https://api-platform.com), a powerful framework for building APIs and web applications.
8 |
9 | This repository contains all the API Platform documentation resources.
10 |
11 | ## Contributing
12 |
13 | Please check our [CONTRIBUTING file](/CONTRIBUTING.md) to contribute.
14 |
15 |
--------------------------------------------------------------------------------
/admin/file-upload.md:
--------------------------------------------------------------------------------
1 | # Handling File Upload
2 |
3 | If you need to handle the file upload in the server part, please follow [the related documentation](../symfony/file-upload.md).
4 |
5 | This documentation assumes you have a `/media_objects` endpoint accepting `multipart/form-data`-encoded data.
6 |
7 | To manage the upload in the admin part, you need to [customize the guessed create or edit form](./customizing.md#from-inputguesser-to-react-admin-inputs).
8 |
9 | Add a [``](https://marmelab.com/react-admin/FileInput.html) as a child of the guesser. For example, for the create form:
10 |
11 | ```js
12 | import {
13 | HydraAdmin,
14 | ResourceGuesser,
15 | CreateGuesser,
16 | } from '@api-platform/admin';
17 | import { FileField, FileInput } from 'react-admin';
18 |
19 | const MediaObjectsCreate = () => (
20 |
21 |
22 |
23 |
24 |
25 | );
26 |
27 | export const App = () => (
28 |
29 |
30 | {/* ... */}
31 |
32 | );
33 | ```
34 |
35 | And that's it!
36 | The guessers are able to detect that you have used a `FileInput` and are passing this information to the data provider, through a `hasFileField` field in the `extraInformation` object, itself in the data.
37 | If you are using the Hydra data provider, it uses a `multipart/form-data` request instead of a JSON-LD one.
38 |
39 | **Note:** In the case of the `EditGuesser`, the HTTP method used becomes a `POST` instead of a `PUT`, to prevent a [PHP bug](https://bugs.php.net/bug.php?id=55815).
40 |
--------------------------------------------------------------------------------
/admin/getting-started.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | ## API Platform Symfony variant
4 |
5 | If you use the [API Platform Symfony variant](../symfony/), good news, API Platform Admin is already installed! 🎉
6 |
7 | You can access it by visiting `/admin` on your API Platform application.
8 |
9 | When running locally, you can also click on the "Admin" button of the welcome page at [https://localhost](https://localhost).
10 |
11 | 
12 |
13 | Here is what it looks like with a simple API exposing a `Greetings` resource:
14 |
15 | 
16 |
17 | ## Manual Installation
18 |
19 | If you did not use the Symfony variant of API Platform and need to install API Platform Admin manually, follow this guide.
20 |
21 | First, let's scaffold a React Admin Application by using the [Create React Admin](https://marmelab.com/react-admin/CreateReactAdmin.html) tool:
22 |
23 | ```bash
24 | npx create-react-admin@latest my-admin
25 | cd my-admin
26 | ```
27 |
28 | Then, install the `@api-platform/admin` library:
29 |
30 | ```bash
31 | npm install @api-platform/admin
32 | ```
33 |
34 | Now you can use either:
35 |
36 | - [``](./getting-started.md#using-hydraadmin) to connect your app to an API exposing a Hydra documentation
37 | - [``](./getting-started.md#using-openapiadmin) to connect your app to an API exposing an OpenAPI documentation
38 |
39 | ## Using `HydraAdmin`
40 |
41 | You can use the [``](./components.md#hydraadmin) component exported by `@api-platform/admin` to connect your app to an API exposing a Hydra documentation.
42 |
43 | If you used Create React Admin, you can replace the content of `src/App.tsx` by:
44 |
45 | ```tsx
46 | import { HydraAdmin } from "@api-platform/admin";
47 |
48 | // Replace with your own API entrypoint
49 | // For instance if https://example.com/api/books is the path to the collection of book resources, then the entrypoint is https://example.com/api
50 | export const App = () => ;
51 | ```
52 |
53 | **Tip:** if you don't want to hardcode the API URL, you can [use an environment variable](https://vite.dev/guide/env-and-mode).
54 |
55 | Your new administration interface is ready! `HydraAdmin` will automatically fetch the Hydra documentation of your API and generate CRUD pages for all the resources it exposes.
56 |
57 | Type `npm run dev` to try it!
58 |
59 | 
60 |
61 | **Tip:** There are more props you can pass to the `HydraAdmin` component to customize the dataProvider or the connection to Mercure. Check the [API documentation](./components.md#hydraadmin) for more information.
62 |
63 | **Tip:** You may also need to configure your API to set the correct CORS headers. Refer to the [Configuring CORS](./getting-started.md#configuring-cors) section below to learn more.
64 |
65 | ## Using `OpenApiAdmin`
66 |
67 | You can use the [``](./components.md#openapiadmin) component exported by `@api-platform/admin` to connect your app to an API exposing an OpenAPI documentation.
68 |
69 | If you used Create React Admin, you can replace the content of `src/App.tsx` by:
70 |
71 | ```tsx
72 | import { OpenApiAdmin } from "@api-platform/admin";
73 |
74 | // Replace with your own API entrypoint
75 | export const App = () => (
76 |
80 | );
81 | ```
82 |
83 | **Tip:** If you don't want to hardcode the API URL, you can use an environment variable (see [Vite.js](https://vite.dev/guide/env-and-mode) or [Next.js](https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables) docs).
84 |
85 | Your new administration interface is ready! `OpenApiAdmin` will automatically fetch the Hydra documentation of your API and generate CRUD pages for all the resources it exposes.
86 |
87 | Type `npm run dev` to try it!
88 |
89 | 
90 |
91 | **Tip:** There are more props you can pass to the `OpenApiAdmin` component to customize the dataProvider or the connection to Mercure. Check the [API documentation](./components.md#openapiadmin) for more information.
92 |
93 | **Tip:** You may also need to configure your API to set the correct CORS headers. Refer to the [Configuring CORS](./getting-started.md#configuring-cors) section below to learn more.
94 |
95 | ## Configuring CORS
96 |
97 | Be sure to make your API send proper [CORS HTTP headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) to allow
98 | the admin's domain to access it.
99 |
100 | To do so, if you use the API Platform Symfony variant, update the value of the `CORS_ALLOW_ORIGIN` parameter in `api/.env` (it will be set to `^https?://localhost:?[0-9]*$`
101 | by default).
102 |
103 | If you use a custom installation of Symfony and [API Platform Core](../core/), you will need to adjust the [NelmioCorsBundle configuration](https://github.com/nelmio/NelmioCorsBundle#configuration) to expose the `Link` HTTP header and to send proper CORS headers on the route under which the API will be served (`/api` by default).
104 | Here is a sample configuration:
105 |
106 | ```yaml
107 | # config/packages/nelmio_cors.yaml
108 |
109 | nelmio_cors:
110 | paths:
111 | '^/api/':
112 | origin_regex: true
113 | allow_origin: ['^http://localhost:[0-9]+'] # You probably want to change this regex to match your real domain
114 | allow_methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE']
115 | allow_headers: ['Content-Type', 'Authorization']
116 | expose_headers: ['Link']
117 | max_age: 3600
118 | ```
119 |
120 | Clear the cache to apply this change:
121 |
122 | ```console
123 | bin/console cache:clear --env=prod
124 | ```
125 |
126 | ## Next Step
127 |
128 | Learn how to add more features to your generated Admin by [Customizing the Schema](./schema.md).
--------------------------------------------------------------------------------
/admin/images/AutocompleteInput.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/AutocompleteInput.png
--------------------------------------------------------------------------------
/admin/images/admin-custom-edit-guesser.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/admin-custom-edit-guesser.png
--------------------------------------------------------------------------------
/admin/images/admin-custom-field.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/admin-custom-field.png
--------------------------------------------------------------------------------
/admin/images/admin-custom-input.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/admin-custom-input.png
--------------------------------------------------------------------------------
/admin/images/admin-custom-list-field-guesser.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/admin-custom-list-field-guesser.png
--------------------------------------------------------------------------------
/admin/images/admin-custom-list-guesser.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/admin-custom-list-guesser.png
--------------------------------------------------------------------------------
/admin/images/admin-custom-show-guesser.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/admin-custom-show-guesser.png
--------------------------------------------------------------------------------
/admin/images/admin-datagrid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/admin-datagrid.png
--------------------------------------------------------------------------------
/admin/images/admin-default-list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/admin-default-list.png
--------------------------------------------------------------------------------
/admin/images/admin-demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/admin-demo.gif
--------------------------------------------------------------------------------
/admin/images/admin-demo.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/admin-demo.mp4
--------------------------------------------------------------------------------
/admin/images/admin-demo.webm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/admin-demo.webm
--------------------------------------------------------------------------------
/admin/images/admin-filter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/admin-filter.png
--------------------------------------------------------------------------------
/admin/images/admin-form-layout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/admin-form-layout.png
--------------------------------------------------------------------------------
/admin/images/admin-menu-icons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/admin-menu-icons.png
--------------------------------------------------------------------------------
/admin/images/admin-menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/admin-menu.png
--------------------------------------------------------------------------------
/admin/images/admin-reference-record-count.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/admin-reference-record-count.png
--------------------------------------------------------------------------------
/admin/images/admin-sort.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/admin-sort.png
--------------------------------------------------------------------------------
/admin/images/admin-tabbed-show-layout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/admin-tabbed-show-layout.png
--------------------------------------------------------------------------------
/admin/images/admin-undoable-mutation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/admin-undoable-mutation.png
--------------------------------------------------------------------------------
/admin/images/admin-warnWhenUnsavedChanges.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/admin-warnWhenUnsavedChanges.png
--------------------------------------------------------------------------------
/admin/images/api-platform-admin-theme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/api-platform-admin-theme.png
--------------------------------------------------------------------------------
/admin/images/api-platform-welcome-page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/api-platform-welcome-page.png
--------------------------------------------------------------------------------
/admin/images/basic-admin-greetings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/basic-admin-greetings.png
--------------------------------------------------------------------------------
/admin/images/embedded-relation-ReferenceField.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/embedded-relation-ReferenceField.png
--------------------------------------------------------------------------------
/admin/images/embedded-relation-ReferenceInput.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/embedded-relation-ReferenceInput.png
--------------------------------------------------------------------------------
/admin/images/embedded-relation-dot-notation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/embedded-relation-dot-notation.png
--------------------------------------------------------------------------------
/admin/images/embedded-relation-full-object.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/embedded-relation-full-object.png
--------------------------------------------------------------------------------
/admin/images/embedded-relation-useEmbedded-false.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/embedded-relation-useEmbedded-false.png
--------------------------------------------------------------------------------
/admin/images/react-admin-theme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/react-admin-theme.png
--------------------------------------------------------------------------------
/admin/images/related-record-with-iri.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/related-record-with-iri.png
--------------------------------------------------------------------------------
/admin/images/related-record-with-name.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/related-record-with-name.png
--------------------------------------------------------------------------------
/admin/images/required-field.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/required-field.png
--------------------------------------------------------------------------------
/admin/images/submission-error-field.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/api-platform/docs/22340ba1a28490caa3795569103a7ec162549263/admin/images/submission-error-field.png
--------------------------------------------------------------------------------
/admin/index.md:
--------------------------------------------------------------------------------
1 | # The API Platform Admin
2 |
3 |
8 |
9 | API Platform **Admin** is a tool to automatically create a beautiful (Material Design) and fully-featured administration interface
10 | for any API implementing specification formats supported by [`@api-platform/api-doc-parser`](https://github.com/api-platform/api-doc-parser).
11 |
12 | In particular, that includes:
13 |
14 | - APIs using [the Hydra Core Vocabulary](https://www.hydra-cg.com/)
15 | - APIs exposing an [OpenAPI documentation](https://www.openapis.org/)
16 |
17 | Of course, API Platform Admin is the perfect companion of APIs created
18 | using [the API Platform framework](https://api-platform.com). But it also supports APIs written with any other programming language or framework as long as they expose a standard Hydra or OpenAPI documentation.
19 |
20 | ## Based On React Admin
21 |
22 | API Platform Admin is a Single Page Application (SPA), based on [React Admin](https://marmelab.com/react-admin/), a powerful frontend framework for building B2B applications on top of REST/GraphQL APIs, written in TypeScript and React.
23 |
24 | Thanks to its built-in **guessers**, API Platform Admin parses the API documentation then uses React Admin to expose a nice, responsive management interface (Create-Retrieve-Update-Delete, i.e. CRUD) for all documented resource types.
25 |
26 | Afterwards, you can **customize everything** by using the numerous components provided by [React Admin](https://marmelab.com/react-admin/documentation.html) and [MUI](https://mui.com/), or even writing your own [React](https://reactjs.org/) components.
27 |
28 |
29 |
30 |
31 |
32 | ## Features
33 |
34 | Simply by reading your API documentation, API Platform Admin provides the following features:
35 |
36 | - Generate 'list', 'create', 'show', and 'edit' views for all resources
37 | - Automatically detect the type for inputs and fields
38 | - Client-side [validation](./validation.md) on required inputs
39 | - Pagination
40 | - Filtering and ordering
41 | - Easily view and edit [related records](./handling-relations.md)
42 | - Display the related resource’s name instead of its IRI ([using the Schema.org vocabulary](./schema.md#displaying-related-resources-name-instead-of-its-iri))
43 | - Nicely displays server-side errors (e.g. advanced validation)
44 | - Real-time updates with [Mercure](https://mercure.rocks)
45 |
46 | By [leveraging React Admin components](./advanced-customization.md), you can further customize the generated interface and get access to many more features:
47 |
48 | - Powerful Datagrid components
49 | - Search and filtering
50 | - Advanced form validation
51 | - Undoable mutations
52 | - Authentication
53 | - Access Control
54 | - Internationalization
55 | - [And many more](https://marmelab.com/react-admin/Features.html)
56 |
57 | ## Next Step
58 |
59 | Get your Admin up and running by following the [Getting Started guide](./getting-started.md).
--------------------------------------------------------------------------------
/admin/performance.md:
--------------------------------------------------------------------------------
1 | # Performance Tips
2 |
3 | To make the admin faster and greener, you can make some changes to your API.
4 |
5 | ## Retrieve All Relations in One Request
6 |
7 | By default, if your relations are not embedded and if you decide to display some fields belonging to relations in your resource list,
8 | the admin will fetch the relations one by one.
9 |
10 | In this case, it can be improved by doing only one request for all the related resources instead.
11 |
12 | To do so, you need to make sure the [search filter](../core/doctrine-filters.md#search-filter) is enabled for the identifier of the related resource.
13 |
14 | For instance, if you have a `book` resource having a relation to `author` resources and you display the author names on your book list,
15 | you can make sure the authors are retrieved in one go by writing:
16 |
17 | ```php
18 | ` or `` component:
14 |
15 | ```javascript
16 | import { OpenApiAdmin } from '@api-platform/admin';
17 |
18 | export default () => (
19 |
24 | );
25 | ```
26 |
27 | Or in the data provider factory:
28 |
29 | ```javascript
30 | import { hydraDataProvider, fetchHydra } from '@api-platform/admin';
31 | import { parseHydraDocumentation } from '@api-platform/api-doc-parser';
32 |
33 | const dataProvider = baseHydraDataProvider({
34 | entrypoint,
35 | httpClient: fetchHydra,
36 | apiDocumentationParser: parseHydraDocumentation,
37 | mercure: { hub: 'https://mercure.rocks/hub' },
38 | });
39 | ```
40 |
41 | The `mercure` object can take the following properties:
42 |
43 | - `hub`: the URL to your Mercure hub (default value: null ; when null it will be discovered by using API responses)
44 | - `jwt`: a subscriber JWT to access your Mercure hub (default value: null)
45 | - `topicUrl`: the topic URL of your resources (default value: entrypoint)
46 |
--------------------------------------------------------------------------------
/admin/schema.md:
--------------------------------------------------------------------------------
1 | # Customizing the Schema
2 |
3 | Both [`HydraAdmin`](./components.md#hydraadmin) and [`OpenApiAdmin`](./components.md#openapiadmin) leverage introspection of the API schema to discover its capabilities, like **filtering** and **sorting**.
4 |
5 | They also detect wether the API has real-time capabilities using [Mercure](./real-time-mercure.md), and automatically enable it if it does.
6 |
7 | Lastly, API Platform Admin has native support for the popular [Schema.org](./schema.md#about-schemaorg) vocabulary, which enables it to automatically use the field type matching your data, or display a related resource's name instead of its IRI.
8 |
9 | ## Adding Filtering Capabilities
10 |
11 | You can add the [`ApiFilter` attribute](../core/filters.md#apifilter-attribute) to an API Platform resource to configure a filter on a property.
12 |
13 | For instance, here is how configure filtering on the `id`, `title` and `author` properties of a `Book` resource:
14 |
15 | ```php
16 | 'exact',
29 | 'title' => 'ipartial',
30 | 'author' => 'ipartial'
31 | ])]
32 | class Book
33 | {
34 | // ...
35 | }
36 | ```
37 |
38 | If you are using the guessers, the Admin will automatically update the Book list view to include a filter on the selected properties.
39 |
40 | 
41 |
42 | **Tip:** Learn more about the [`ApiFilter` attribute](../core/filters.md#apifilter-attribute) in the core documentation.
43 |
44 | ## Adding Sorting Capabilities
45 |
46 | You can also use the [`ApiFilter` attribute](../core/filters.md#apifilter-attribute) on an API Plaform resource to configure sorting.
47 |
48 | For instance, here is how to configure sorting on the `id`, `isbn`, `title`, `author` and `publicationDate` properties of a `Book` resource:
49 |
50 | ```php
51 | 'ASC',
64 | 'isbn' => 'ASC',
65 | 'title' => 'ASC',
66 | 'author' => 'ASC',
67 | 'publicationDate' => 'DESC'
68 | ])]
69 | class Book
70 | {
71 | // ...
72 | }
73 | ```
74 |
75 | If you are using the guessers, the Admin will automatically update the Book list view to make the selected columns sortable.
76 |
77 | 
78 |
79 | **Tip:** Learn more about the [`ApiFilter` attribute](../core/filters.md#apifilter-attribute) in the core documentation.
80 |
81 | ## Enabling Real-Time Updates
82 |
83 | You can use the `mercure` attribute to hint API Platform that it must dispatch the updates regarding the given resources to the Mercure hub:
84 |
85 | ```php
86 | Schema.org is a collaborative, community activity with a mission to create, maintain, and promote schemas for structured data on the Internet, on web pages, in email messages, and beyond.
108 |
109 | To leverage this capability, your API must use the JSON-LD format and the appropriate Schema.org types.
110 | The following examples will use [API Platform Core](../core/) to create such API, but keep in mind that this feature will work with any JSON-LD API using the Schema.org vocabulary, regardless of the used web framework or programming language.
111 |
112 | ## Displaying Related Resource's Name Instead of its IRI
113 |
114 | By default, IRIs of related objects are displayed in lists and forms.
115 | However, it is often more user-friendly to display a string representation of the resource (such as its name) instead of its ID.
116 |
117 | To configure which property should be shown to represent your entity, map the property containing the name of the object with the `https://schema.org/name` type:
118 |
119 | ```php
120 | // api/src/Entity/Person.php
121 | ...
122 |
123 | #[ApiProperty(iris: ["https://schema.org/name"])]
124 | private $name;
125 |
126 | ...
127 | ```
128 |
129 | | With IRI | With Resource Name |
130 | | ---------------------------------------------------------------- | ---------------------------------------------------------------------------- |
131 | |  |  |
132 |
133 | ## Emails, URLs and Identifiers
134 |
135 | Besides, it is also possible to use the documentation to customize some fields automatically while configuring the semantics of your data.
136 |
137 | The following Schema.org types are currently supported by API Platform Admin:
138 |
139 | - `https://schema.org/email`: the field will be rendered using the [``](https://marmelab.com/react-admin/EmailField.html) React Admin component
140 | - `https://schema.org/url`: the field will be rendered using the [``](https://marmelab.com/react-admin/UrlField.html) React Admin component
141 | - `https://schema.org/identifier`: the field will be formatted properly in inputs
142 |
143 | Note: if you already use validation on your properties, the semantics are already configured correctly (see [the correspondence table](../core/validation.md#open-vocabulary-generated-from-validation-metadata))!
144 |
145 | ## Next Step
146 |
147 | Learn how to tweak the generated Admin by [Customizing the Guessers](./customizing.md).
148 |
--------------------------------------------------------------------------------
/admin/validation.md:
--------------------------------------------------------------------------------
1 | # Validation
2 |
3 | API Platform Admin manages automatically two types of validation: client-side validation and server-side (or submission) validation.
4 |
5 | ## Client-side Validation
6 |
7 | If the API documentation indicates that a field is mandatory,
8 | API Platform Admin will automatically add a [required client-side validation](https://marmelab.com/react-admin/Validation.html#per-input-validation-built-in-field-validators).
9 |
10 | For instance, with API Platform as backend, if you write the following:
11 |
12 | ```php
13 | ` with a React Admin [input component](https://marmelab.com/react-admin/Inputs.html), such as [``](https://marmelab.com/react-admin/TextInput.html), [``](https://marmelab.com/react-admin/DateInput.html) or [``](https://marmelab.com/react-admin/ReferenceInput.html), you will need to **manually add the validation rules back**.
66 |
67 | Fortunately, this is very easy to do, thanks to the [`validate`](https://marmelab.com/react-admin/Inputs.html#validate) prop of the input components.
68 |
69 | For instance, here is how to replace the input for the required `title` field:
70 |
71 | ```diff
72 | import { EditGuesser, InputGuesser } from '@api-platform/admin';
73 | +import { TextInput, required } from 'react-admin';
74 |
75 | export const BookEdit = () => (
76 |
77 | -
78 | +
79 |
80 | );
81 | ```
82 |
83 | React Admin already comes with several [built-in validators](https://marmelab.com/react-admin/Validation.html#per-input-validation-built-in-field-validators), such as:
84 |
85 | * `required(message)` if the field is mandatory,
86 | * `minValue(min, message)` to specify a minimum value for integers,
87 | * `maxValue(max, message)` to specify a maximum value for integers,
88 | * `minLength(min, message)` to specify a minimum length for strings,
89 | * `maxLength(max, message)` to specify a maximum length for strings,
90 | * `number(message)` to check that the input is a valid number,
91 | * `email(message)` to check that the input is a valid email address,
92 | * `regex(pattern, message)` to validate that the input matches a regular expression,
93 | * `choices(list, message)` to validate that the input is within a given list
94 |
95 | React Admin also supports [Global Validation](https://marmelab.com/react-admin/Validation.html#global-validation) (at the form level).
96 |
97 | Check out the [Form Validation](https://marmelab.com/react-admin/Validation.html) documentation to learn more.
98 |
--------------------------------------------------------------------------------
/core/client-integration.md:
--------------------------------------------------------------------------------
1 | # Client Integrations
2 |
3 | ## Edge Side API (ESA)
4 |
5 | > [Edge Side APIs (ESA)](https://edge-side-api.rocks/) is an architectural pattern that allows the creation of more
6 | > reliable, efficient, and less resource-intensive APIs. It revives the core REST/HATEOAS principles while taking full
7 | > advantage of the new capabilities provided by the web platform.
8 | >
9 | > ESA promotes a mixed approach (synchronous and asynchronous), offering simplicity in development and use, exceptional
10 | > performance, and the ability for clients to receive real-time updates of the resources they fetched. ESA also leverages
11 | > existing standards to expose API documentation, enabling the creation of generic clients capable of discovering the
12 | > API’s capabilities at runtime.
13 | >
14 | > — *From [ESA White Paper](https://edge-side-api.rocks/white-paper)*
15 |
16 | ## JavaScript Client Integrations
17 |
18 | API Platform offers a suite of tools and libraries that streamline the integration of JavaScript clients with APIs.
19 | These tools simplify development by automating tasks such as data fetching, administration panel creation,
20 | and real-time updates. Below is a detailed overview of the available clients, libraries, and their usage.
21 |
22 | ### Clients and Tools Overview
23 |
24 | #### Admin
25 |
26 | API Platform Admin is a dynamic administration panel generator built with [React-Admin](https://marmelab.com/react-admin/).
27 | It automatically adapts to your API schema and provides extensive customization options. It can read an [OpenAPI](https://www.openapis.org/)
28 | specification or a [Hydra](https://www.hydra-cg.com/) specification. API Platform supports both [OpenAPI](openapi.md) and
29 | [Hydra](extending-jsonld-context.md#hydra) from scratch!
30 |
31 | [Learn more about API Platform Admin](../admin/index.md).
32 |
33 | #### Create Client
34 |
35 | The Client Generator creates JavaScript/TypeScript clients based on your API documentation. It generates code that
36 | integrates seamlessly with your API endpoints, reducing development time and errors.
37 |
38 | [Learn more about the Create Client](../create-client/index.md)
39 |
40 | ### JavaScript Libraries
41 |
42 | #### api-platform/ld
43 |
44 | The [api-platform/ld](https://edge-side-api.rocks/linked-data) JavaScript library simplifies working with Linked Data.
45 | It helps parse and serialize data in formats such as [JSON-LD](extending-jsonld-context.md#json-ld), making it easier to
46 | handle complex relationships in your applications.
47 |
48 | For example, let's load authors when required with a Linked Data approach.
49 | Given an API referencing books and their authors, where `GET /books/1` returns:
50 |
51 | ```json
52 | {
53 | "@id": "/books/1",
54 | "@type": ["https://schema.org/Book"],
55 | "title": "Hyperion",
56 | "author": "https://localhost/authors/1"
57 | }
58 | ```
59 |
60 | Use an [URLPattern](https://urlpattern.spec.whatwg.org/) to load authors automatically when fetching an author property
61 | such as `books.author?.name`:
62 |
63 | ```javascript
64 | import ld from '@api-platform/ld'
65 |
66 | const pattern = new URLPattern("/authors/:id", "https://localhost");
67 | const books = await ld('/books', {
68 | urlPattern: pattern,
69 | onUpdate: (newBooks) => {
70 | log()
71 | }
72 | })
73 |
74 | function log() {
75 | console.log(books.author?.name)
76 | }
77 |
78 | log()
79 | ```
80 |
81 | With [api-platform/ld](https://edge-side-api.rocks/linked-data), authors are automatically loaded when needed.
82 |
83 | [Read the full documentation](https://edge-side-api.rocks/linked-data).
84 |
85 | #### api-platform/mercure
86 |
87 | [Mercure](https://mercure.rocks/spec) is a real-time communication protocol. The [api-platform/mercure](https://edge-side-api.rocks/mercure)
88 | library enables you to subscribe to updates and deliver real-time data seamlessly.
89 |
90 | Our frontend library allows you to subscribe to updates with efficiency, re-using the hub connection and adding topics
91 | automatically as they get requested. API Platform [supports Mercure](mercure.md) and automatically sets the
92 | [Link header](https://mercure.rocks/spec#content-negotiation) making auto-discovery a breeze. For example:
93 |
94 | ```javascript
95 | import mercure, { close } from "@api-platform/mercure";
96 |
97 | const res = await mercure('https://localhost/authors/1', {
98 | onUpdate: (author) => console.log(author)
99 | })
100 |
101 | const author = res.then(res => res.json())
102 |
103 | // Close if you need to
104 | history.onpushstate = function(e) {
105 | close('https://localhost/authors/1')
106 | }
107 | ```
108 |
109 | Assuming `/authors/1` returned the following:
110 |
111 | ```http
112 | Link: ; rel="self"
113 | Link: ; rel="mercure"
114 | ```
115 |
116 | An `EventSource` subscribes to the topic `https://localhost/authors/1` on the hub `https://localhost/.well-known/mercure`.
117 |
118 | [Read the full documentation](https://edge-side-api.rocks/mercure).
119 |
120 | #### api-platform/api-doc-parser
121 |
122 | The [api-platform/api-doc-parser](https://github.com/api-platform/api-doc-parser) that parses Hydra, Swagger,
123 | OpenAPI, and GraphQL documentation into an intermediate format for generating API clients and scaffolding code.
124 | It integrates well with API Platform and supports auto-detecting resource relationships.
125 |
126 | Key Features:
127 |
128 | - Multi-format support: Parses Hydra, Swagger (OpenAPI v2), OpenAPI v3, and GraphQL.
129 | - Intermediate representation: Converts API docs into a usable format for generating clients, scaffolding code, or building admin interfaces.
130 | - API Platform integration: Works seamlessly with API Platform.
131 | - Auto-detection of resource relationships: Automatically detects relationships between resources based on documentation.
132 |
133 | Example: Parsing [Hydra](http://hydra-cg.com/) API Documentation:
134 |
135 | ```javascript
136 | import { parseHydraDocumentation } from '@api-platform/api-doc-parser';
137 |
138 | parseHydraDocumentation('https://demo.api-platform.com').then(({api}) => console.log(api));
139 | ```
140 | This example fetches Hydra documentation from `https://demo.api-platform.com`, parses it, and logs the resulting API
141 | structure. The `parseHydraDocumentation` method is particularly useful for building metadata-driven clients or handling advanced API interactions.
142 |
143 | [Read the full documentation](https://github.com/api-platform/api-doc-parser).
144 |
--------------------------------------------------------------------------------
/core/default-order.md:
--------------------------------------------------------------------------------
1 | # Overriding Default Order
2 |
3 | API Platform provides an easy way to override the default order of items in your collection.
4 |
5 | By default, items in the collection are ordered in ascending (ASC) order by their resource identifier(s). If you want to
6 | customize this order, you must add an `order` attribute on your ApiResource annotation:
7 |
8 |
9 |
10 | ```php
11 | 'ASC'])]
18 | class Book
19 | {
20 | // ...
21 |
22 | /**
23 | * ...
24 | */
25 | public $foo;
26 |
27 | // ...
28 | }
29 | ```
30 |
31 | ```yaml
32 | # api/config/api_platform/resources/Book.yaml
33 | # The YAML syntax is only supported for Symfony
34 | App\ApiResource\Book:
35 | order:
36 | foo: ASC
37 | ```
38 |
39 |
40 |
41 | This `order` attribute is used as an array: the key defines the order field, the values defines the direction.
42 | If you only specify the key, `ASC` direction will be used as default. For example, to order by `foo` & `bar`:
43 |
44 |
45 |
46 | ```php
47 |
80 |
81 | It's also possible to configure the default order on an association property:
82 |
83 |
84 |
85 | ```php
86 |
114 |
115 | Another possibility is to apply the default order for a specific collection operation, which will override the global default order configuration.
116 |
117 |
118 |
119 | ```php
120 | 'DESC'])],
130 | new GetCollection(name: 'get_asc_custom', uriTemplate: 'custom_collection_asc_foos', order: ['name' => 'ASC'])]
131 | ])]
132 | class Book
133 | {
134 | // ...
135 |
136 | /**
137 | * @var string
138 | */
139 | public $name;
140 |
141 | // ...
142 | }
143 | ```
144 |
145 | ```yaml
146 | # api/config/api_platform/resources/Book.yaml
147 | # The YAML syntax is only supported for Symfony
148 | App\ApiResource\Book:
149 | ApiPlatform\Metadata\GetCollection: ~
150 | get_desc_custom:
151 | class: ApiPlatform\Metadata\GetCollection
152 | uriTemplate: custom_collection_desc_foos
153 | order:
154 | name: DESC
155 | get_asc_custom:
156 | class: ApiPlatform\Metadata\GetCollection
157 | uriTemplate: custom_collection_asc_foos
158 | order:
159 | name: ASC
160 | ```
161 |
162 |
163 |
--------------------------------------------------------------------------------
/core/design.md:
--------------------------------------------------------------------------------
1 | # General Design Considerations
2 |
3 | Since you only need to describe the structure of the data to expose, API Platform is both [a "design-first" and "code-first"](https://swagger.io/blog/api-design/design-first-or-code-first-api-development/)
4 | API framework. However, the "design-first" methodology is strongly recommended: first you design the **public shape** of
5 | API endpoints.
6 |
7 | To do so, you have to write a plain old PHP object (POPO) representing the input and output of your endpoint. This is the class
8 | that is [marked with the `#[ApiResource]` attribute](../symfony/index.md).
9 | This class **doesn't have** to be mapped with Doctrine ORM, or any other persistence system. It must be simple (it's usually
10 | just a data structure with no or minimal behaviors) and will be automatically converted to [Hydra](extending-jsonld-context.md),
11 | [OpenAPI](openapi.md) and [GraphQL](graphql.md) documentations or schemas by API Platform (there is a 1-1 mapping
12 | between this class and those docs).
13 |
14 | Then, it's up to the developer to feed API Platform with an hydrated instance of this API resource object by implementing
15 | the [`ProviderInterface`](state-providers.md). Basically, the state provider will query the persistence system (RDBMS,
16 | document or graph DB, external API...), and must hydrate and return the POPO that has been designed as mentioned above.
17 |
18 | When updating a state (`POST`, `PUT`, `PATCH`, `DELETE` HTTP methods), it's up to the developer to properly persist the
19 | data provided by API Platform's resource object [hydrated by the serializer](serialization.md).
20 | To do so, there is another interface to implement: [`ProcessorInterface`](state-processors.md).
21 |
22 | This class will read the API resource object (the one marked with `#[ApiResource]`) and:
23 |
24 | - persist it directly in the database;
25 | - or hydrate a DTO then trigger a command;
26 | - or populate an event store;
27 | - or persist the data in any other useful way.
28 |
29 | The logic of state processors is the responsibility of application developers, and is **out of the API Platform's scope**.
30 |
31 | For [Rapid Application Development](https://en.wikipedia.org/wiki/Rapid_application_development), convenience and prototyping,
32 | **if and only if the class marked with `#[ApiResource]` is also a Doctrine entity**, the developer can use the Doctrine
33 | ORM's state provider and processor implementations shipped with API Platform.
34 |
35 | In this case, the public (`#[ApiResource]`) and internal (Doctrine entity) data models are shared. Then, API Platform will
36 | be able to query, filter, paginate and persist data automatically.
37 | This approach is super-convenient and efficient, but is probably **not a good idea** for non-[CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete)
38 | and/or large systems.
39 | Again, it's up to the developers to use, or to not use these built-in state providers/processors depending on the business logic
40 | they are dealing with.
41 | API Platform makes it easy to create custom state providers and processors.
42 | It also makes it easy to implement patterns such as [CQS](https://www.martinfowler.com/bliki/CommandQuerySeparation.html)
43 | or [CQRS](https://martinfowler.com/bliki/CQRS.html) thanks to [the Messenger Component integration](../symfony/messenger.md) and the [DTO support](dto.md).
44 |
45 | Last but not least, to create [Event Sourcing](https://martinfowler.com/eaaDev/EventSourcing.html)-based systems, a convenient
46 | approach is:
47 |
48 | - to persist data in an event store using a Messenger handler or a custom [state processor](state-processors.md)
49 | - to create projections in standard RDBMS (PostgreSQL, MariaDB...) tables or views
50 | - to map those projections with read-only Doctrine entity classes **and** to mark those classes with `#[ApiResource]`
51 |
52 | You can then benefit from the built-in Doctrine filters, sorting, pagination, auto-joins and all of [the extension points](extending.md) provided by API Platform.
53 |
--------------------------------------------------------------------------------
/core/extending-jsonld-context.md:
--------------------------------------------------------------------------------
1 | # Extending JSON-LD AND Hydra Contexts
2 |
3 | ## JSON-LD
4 |
5 |