Have you ever wanted to reference your PHP enums in your frontend code but ended up (or didn't want to end up) duplicating them manually? Well here is your answer.
You need both sides to get started.
$ composer require synergitech/laravel-magic-enums
$ npm install --save laravel-magic-enums
- Add the trait and interface from this package to your enums
<?php
namespace App\Enums;
use SynergiTech\MagicEnums\Interfaces\MagicEnum;
use SynergiTech\MagicEnums\Traits\HasMagic;
enum YourEnum: string implements MagicEnum
{
use HasMagic;
...
- Include the route somewhere in your routes file of choice, in this example we are going to create
/api/enums
.
<?php
use Illuminate\Support\Facades\Route;
use SynergiTech\MagicEnums\Facades\MagicEnumsRouteFacade;
Route::prefix('/api')->group(function () {
MagicEnumsRouteFacade::enumsController();
});
You can obviously include middleware on it if you wish, e.g. for an authenticated session, but this may affect your frontend's ability to initialise, so please be careful.
We recommend you don't include sensitive information in your enums.
- We work primarily with Inertia and Vue so the integration looks something like this. Note the use of
async
/await
and reusing the route we created earlier.
import { vueEnumPlugin } from "laravel-magic-enums";
import { createApp, h } from "vue";
import { createInertiaApp } from "@inertiajs/vue3";
createInertiaApp({
resolve: (name) => {
const pages = import.meta.glob("./Pages/**/*.vue");
return pages[`./Pages/${name}.vue`]();
},
async setup({ el, App, props, plugin }) {
createApp({ render: () => h(App, props) })
.use(await vueEnumPlugin("/api/enums"))
.mount(el);
},
...
- During development, you can have Vite reload automatically when your enums change. This is handled by
chokidar
. You might also wish to compile a types definition so your IDE knows the details of the enums. We recommend adding this file to your.gitignore
file.
While not necessary, you can also provide a cli command to prettierCommand
to format the generated TypeScript file according to your project's standards.
Update your vite.config.js
as follows. You'll notice we provide both the directory and the endpoint.
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue';
import { laravelMagicEnums } from "laravel-magic-enums/vite";
export default defineConfig({
plugins: [
laravel({
...
}),
vue({
...
}),
laravelMagicEnums({
enumDir: "./app/Enums",
enumEndpoint: "http://localhost/api/enums",
interfaceOutput: "./resources/js/globals.d.ts",
prettierCommand: "prettier --write",
}),
],
...
- Now in your frontend, you can reference your enums as if they were key-value objects.
import { useEnums } from 'laravel-magic-enums';
const { YourEnum, YourOtherEnum } = useEnums();
You may choose to have an array within your enum of a subset of the values for a specific purpose or grouping.
If you use the PHP attribute SynergiTech\MagicEnums\Attributes\AppendConstToMagic
, then an extra enum representing this will be available in the frontend.
You may also have an array which maps some or all of the values of the enum to a different string.
If you use the PHP attribute SynergiTech\MagicEnums\Attributes\AppendValueToMagic
, then an extra enum representing this will be available in the frontend.
For example:
<?php
namespace App\Enums;
use SynergiTech\MagicEnums\Attributes\AppendConstToMagic;
use SynergiTech\MagicEnums\Attributes\AppendValueToMagic;
use SynergiTech\MagicEnums\Interfaces\MagicEnum;
use SynergiTech\MagicEnums\Traits\HasMagic;
enum TestingEnum: string implements MagicEnum
{
use HasMagic;
case First = 'first';
case Second = 'second';
case Third = 'third';
#[AppendConstToMagic]
public const JUST_ONE = [
self::First,
];
#[AppendValueToMagic]
public const COLOUR = [
self::First->value => 'red',
];
}
Will create the output:
TestingEnum: {
First: {
"name": "First",
"value": "first",
"colour": "red"
},
Second: {
"name": "Second",
"value": "second",
"colour": null
},
Third: {
"name": "Third",
"value": "third",
"colour": null
}
},
TestingEnumJustOne: {
First: {
"name": "First",
"value": "first",
"colour": "red"
}
}
To avoid rebuilding the json everytime the endpoint is requested, you can add a file named VERSION
to your root folder. Magic Enums will determine whether to cache the output based on the time this file was last touched. You can specify a custom cache key in the config.
If you wish to have more control over appending values to your magic enums for the frontend, you can extend the current trait using something along the lines of app/Traits/CustomMagic.php as long as you always follow the interface and provide the function.