Back to Homepage

Bookmark Card in Laravel Livewire

4 min read

Tags:

Livewire
Bookmark Card in Laravel Livewire

This article shows you how to create a dynamic bookmark card using Laravel Livewire, and how to handle image caching efficiently.

Prerequisites:

  1. Basic knowledge of Laravel and Livewire.

  2. Laravel and Livewire installed in your project.

Step-by-Step Implementation:

Step 1: Installation

If not already done, install the required packages:

composer require guzzlehttp/guzzle livewire/livewire

Step 2: Create the Livewire Components

php artisan make:livewire ImageCache
php artisan make:livewire BookmarkCard

Step 3: Design the Livewire Components

app/Http/Livewire/ImageCache.php

namespace App\Http\Livewire;

use Livewire\Component;
use Illuminate\Support\Facades\Storage;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Log;

class ImageCache extends Component
{
    public $imageUrl;
    public $localPath;

    /**
     * Mount the component.
     *
     * @param string $imageUrl
     * @return void
     */
    public function mount($imageUrl) :void
    {
        $this->imageUrl = $imageUrl;
        $this->localPath = $this->cacheImage($imageUrl);
    }

    /**
     * Cache the given image URL and return its local path.
     *
     * @param string $url
     * @return string
     */
    protected function cacheImage($url)
    {
        try {
            $client = new Client();
            $response = $client->get($url);

            $contentType = $response->getHeader('Content-Type')[0];
            $extension = $this->getExtensionFromMimeType($contentType);
            
            $filename = 'cached_images/' . md5($url) . '.' . $extension;

            if (!Storage::exists($filename)) {
                Storage::put($filename, $response->getBody());
            }

            return Storage::url($filename);
        } catch (\Exception $e) {
            Log::error("Error caching image from {$url}. Error: {$e->getMessage()}");
            return asset('images/default_not_found.jpg');
        }
    }

    /**
     * Retrieve the extension corresponding to the given mime type.
     *
     * @param string $mimeType
     * @return string
     */
    protected function getExtensionFromMimeType($mimeType)
    {
        $mimeTypes = [
            'image/jpeg' => 'jpg',
            'image/png'  => 'png',
            'image/gif'  => 'gif',
            'image/webp' => 'webp',
        ];

        return $mimeTypes[$mimeType] ?? 'jpg';
    }

    /**
     * Render the component.
     *
     * @return \Illuminate\View\View
     */
    public function render()
    {
        return view('livewire.image-cache');
    }
}

Now in resources/views/livewire/image-cache.blade.php:

<img src="{{ $localPath }}" alt="Cached Image" />

Now Edit, app/Http/Livewire/BookmarkCard.php:

namespace App\Http\Livewire;

use Livewire\Component;

class BookmarkCard extends Component
{
    public $title;
    public $description;
    public $url;
    public $imageUrl;

    public function mount($title, $description, $url, $imageUrl) : void
    {
        $this->title = $title;
        $this->description = $description;
        $this->url = $url;
        $this->imageUrl = $imageUrl;
    }

    public function render()
    {
        return view('livewire.bookmark-card');
    }
}

resources/views/livewire/bookmark-card.blade.php:

<div>
    <div class="flex border border-gray-300 p-5 space-x-5">

        <!-- Bookmark Card Left Side (Content) -->
        <div class="flex-1 space-y-2">

            <!-- Bookmark Card Header -->
            <h2 class="text-xl font-semibold">
                {{ $title }}
            </h2>
            <!-- Bookmark Card Content -->
            <p class="text-sm leading-snug">
            {{ $description }}
            </p>
            <!-- Link -->
            <a href="{{ $url }}" class="text-blue-500 hover:underline mt-2">Learn More</a>
        </div>
        <!-- Bookmark Card Right Side (Image) -->
        <div class="w-1/3">
            @livewire('components.image-cache', ['imageUrl' => $imageUrl])
        </div>
    </div>
</div>

Step 4: Styling

Place the CSS for the bookmark card in your main CSS file or create a separate file and link it in your layout.

Step 5: Usage

In any blade view, invoke the BookmarkCard component:

@livewire('bookmark-card', [
    'title' => 'Laravel Sage',
    'description' => 'Helping the world learn Laravel.',
    'url' => 'http://laravelsage.com',
    'imageUrl' => 'http://external.com/image.jpg'
])

Step 6: Create Storage Link

Ensure the symbolic link from public/storage to storage/app/public exists:

php artisan storage:link

Step 7: Task Scheduling for Cleaning Old Cached Images

1. Console Command:

Create a console command:

php artisan make:command ClearOldCachedImages
// ... [other use statements]
use Illuminate\Support\Facades\Storage;

protected $signature = 'clear:old-cached-images';
protected $description = 'Clear cached images that are older than a month';

public function handle() : void
{
    $files = Storage::files('cached_images');

    $monthAgo = now()->subMonth();

    foreach ($files as $file) {
        if (Storage::lastModified($file) < $monthAgo->timestamp) {
            Storage::delete($file);
        }
    }

    $this->info('Old cached images cleared!');
}

2. Schedule the task: In app/Console/Kernel.php:

protected function schedule(Schedule $schedule)
{
    // ... other scheduled tasks

    $schedule->command('clear:old-cached-images')->monthly();
}

With these enhancements, you'll have a more robust and efficient system that will handle a wider variety of scenarios, ensuring the best user experience and optimal server performance. Remember to always test thoroughly after implementing such changes!

Conclusion:

With Laravel Livewire, creating dynamic components like a bookmark card becomes a breeze. By integrating image caching, we further enhance the performance and user experience of our application. With the efficient caching mechanism, your images will load faster, saving both time and bandwidth.

Follow @LaravelSage on X → Follow @LaravelSage on Facebook →
Aniket Singh

Aniket Singh

View All Articles

Full-stack developer with a knack for Merging creativity with technical expertise for standout solutions.

Related Articles

data_forget Helper for Laravel

data_forget Helper for Laravel

Since Laravel version 10.15, there is a new utility function called data_forget that allows you to remove keys from an array or object using a "dot" notation.

Laravel Tenant Application with Tenancy

Laravel Tenant Application with Tenancy

You can make your Laravel app multi-tenant using the Tenancy for Laravel Tenant package. This tenancy package lets you make any Laravel application multi-tenant without rewriting it.

Top Laravel Packages for Building Powerful Applications

Top Laravel Packages for Building Powerful Applications

Are you ready to take your Laravel skills to the next level and build extraordinary applications? Look no further! In this blog post, we will unveil a treasure trove of top packages that will revolutionize your development process.

Subscribe for 20+ new Laravel tutorials every week

You can unsubscribe at any time. You'll also get -20% off my courses!

© 2024

 

Laravel Sage

   |    Privacy Policy