Generating and Enforcing UUIDs in Laravel for Immutable Model IDs
Ensure models always have a UUID set.
Table of contents:
Recommended packages to implement:
The Blade UI Kit package has a great out-of-the-box editor. The editor can optionally accept some parameters that can affect the styling and functionality of the editor. One of the editor’s features includes image uploads, this can be done using Spatie’s Media Library package. In this example, we will be associating images to the posts.
The editor is presented as a Blade component as per the below. We can then pass through the editor’s options using a ‘Post’ model. Just to note, Spatie’s package requires the model to preexist within the database, hence the conditionally checking.
{{-- Blade --}}
<x-easy-mde name="content" :options="$post->getEditorOptions()">
{!! $post->content !!}
</x-easy-mde>
class Post extends Model
{
// ...
/**
* @see https://github.com/Ionaru/easy-markdown-editor
*/
public function getEditorOptions(): array
{
$options = [
'minHeight' => '700px',
'tabSize' => 4,
];
if ($this->exists) {
$options = array_merge($options, [
'uploadImage' => true,
'imageUploadEndpoint' => route('admin.posts.images.store', $this),
'imageCSRFToken' => csrf_token(),
'imageCSRFName' => '_token',
'imagePathAbsolute' => false,
]);
}
return $options;
}
}
Below is an example of a dedicated Controller that handles file uploads from the editor and the associating with a given post.
public function store(PostImageRequest $request, Post $post)
{
$request->validate([
'image' => 'required|file',
]);
$image = $post->addMediaFromRequest('image')
->toMediaCollection('post_content_images');
return response()->json([
'data' => [
'filePath' => $image->getPathRelativeToRoot(),
],
]);
}
Lastly, we can have another separate Controller for handling the saving of the post’s content. Also, it’s important to remove any unused images for the post to save on storage space.
$post->update($request->safe()->only([
'content',
]));
$postContent = $post->content;
foreach ($post->getMedia('post_content_images') as $image) {
if (! Str::contains($postContent, $image->getPathRelativeToRoot())) {
$image->delete();
}
}
Now you’ll want to convert the markdown content. You can use Spatie’s markdown package to achieve this i.e.
{{-- Blade --}}
<x-markdown>{!! $post->content !!}</x-markdown>
The only annoyance here is that this component’s name conflicts with that of the Blade UI Kit package. A simple way around this is to just create a dedicated Blade component with a unique, non-conflicting name that just extends Spatie’s.
<?php
namespace App\View\Components;
use Spatie\LaravelMarkdown\MarkdownBladeComponent;
class Markdown extends MarkdownBladeComponent
{
// ...
}
This could then be registered within a Service Provider, like the following:
use App\View\Components\Markdown;
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Blade::component('markdown-renderer', Markdown::class);
}
You may want to make use of Tailwind’s typography library to use the ‘prose’ class. This will nicely present and format the HTML for you.
{{-- Blade --}}
<x-markdown-renderer class="lg:flex-grow [max-width:unset] prose prose-img:w-full prose-img:rounded-md prose:pre:bg-secondary mt-12" theme="one-dark-pro">{!! $post->content !!}</x-markdown-renderer>
Lastly, be sure to reminder the following with regards to the markdown package:
sudo ln -s "$(which node)" /usr/local/bin
node_modules
are present for the project on the serverEnsure models always have a UUID set.
An opinionated approach on how best to handle exporting large amounts of data in Laravel using commands and queues.
Breadcrumbs are a crucial navigation element in web applications, providing users with a clear path to follow within your site's hierarchy. By the end, you'll have an easy-to-use breadcrumb system that enhances your site's user experience.