<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/">
    <channel>
        <title>SysAdmin Journal · Laravel</title>
        <link>https://sysadmin-journal.com/tag/laravel</link>
        <description>Posts tagged with Laravel</description>
        <language>en</language>
        <lastBuildDate>Fri, 13 Mar 2026 09:06:59 +0000</lastBuildDate>
        <atom:link href="https://sysadmin-journal.com/tag/laravel/rss" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        <item>
            <title>How to Deploy a Laravel Application on Google Cloud Run?</title>
            <link>https://sysadmin-journal.com/how-to-deploy-a-laravel-application-on-google-cloud-run</link>
            <guid isPermaLink="true">https://sysadmin-journal.com/how-to-deploy-a-laravel-application-on-google-cloud-run</guid>
            <pubDate>Fri, 13 Mar 2026 09:06:59 +0000</pubDate>
            <dc:creator>Ish Sookun</dc:creator>
            <category>Google Cloud Platform</category>
            <category>Laravel</category>
            <description>Deploy a Laravel application on Google Cloud Run with PHP 8.5, connect to Cloud SQL PostgreSQL, and scale to zero when idle. A practical guide covering containerization, deployment to the africa-south1 region, and tips for handling storage, sessions, and queues in a serverless environment.</description>
            <media:content url="https://sysadmin-journal.com/content/images/2026/03/laravel-on-google-cloud-run.jpeg" medium="image" />
            <content:encoded><![CDATA[<p>Google Cloud Run is a serverless platform that lets you run containerized applications without managing any infrastructure. You push a container, Cloud Run handles scaling — including scaling to zero when there's no traffic, which means you only pay for what you use.</p><p>For someone like me who has been deploying Laravel applications on traditional Compute Engine instances and Kubernetes clusters, Cloud Run feels like a breath of fresh air for certain workloads. Not everything needs a full-blown GKE cluster or a dedicated VM running 24/7. Sometimes you just need your app to be available, scale when needed, and not cost you anything when it's idle.</p><p>What makes this particularly interesting right now is that Google Cloud has made the <strong>PHP 8.5 runtime generally available on Cloud Run</strong>. If you're running Laravel 12 on PHP 8.5 — as I am — this is great news.</p><h2 id="why-cloud-run-for-laravel">Why Cloud Run for Laravel?</h2><p>Laravel is traditionally deployed on a web server like Nginx or Apache, sitting behind PHP-FPM, on a Linux server you manage yourself. That's perfectly fine for production workloads that need full control. But for staging environments, internal tools, API backends, or even personal projects, Cloud Run removes a lot of the operational overhead.</p><p>Key advantages that stand out for me:</p><ul><li><strong>Scale to zero</strong> — no traffic, no cost. This is ideal for development and staging environments.</li><li><strong>Automatic HTTPS</strong> — Cloud Run provisions and manages TLS certificates for you.</li><li><strong>Built-in revision management</strong> — every deployment creates a new revision, making rollbacks trivial.</li><li><strong>Regional deployment</strong> — and yes, <code>africa-south1</code> (Johannesburg) is supported, which means latency from Mauritius is reasonable thanks to the submarine cable connectivity.</li></ul><h2 id="preparing-your-laravel-application">Preparing Your Laravel Application</h2><p>Before deploying to Cloud Run, your Laravel application needs to be containerized. If you've worked with Docker before — and if you're deploying Laravel in 2026, you probably have — this is straightforward.</p><p>Create a <code>Dockerfile</code> in the root of your Laravel project:</p><pre><code>FROM php:8.5-apache

RUN apt-get update &amp;&amp; apt-get install -y \
    libpng-dev \
    libonig-dev \
    libxml2-dev \
    zip \
    unzip \
    &amp;&amp; docker-php-ext-install pdo_pgsql mbstring exif pcntl bcmath gd

RUN a2enmod rewrite

ENV APACHE_DOCUMENT_ROOT=/var/www/html/public
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf

COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

WORKDIR /var/www/html
COPY . .

RUN composer install --no-dev --optimize-autoloader
RUN php artisan config:cache &amp;&amp; php artisan route:cache &amp;&amp; php artisan view:cache

RUN chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache

EXPOSE 8080

RUN sed -i 's/80/8080/g' /etc/apache2/sites-available/000-default.conf /etc/apache2/ports.conf

CMD ["apache2-foreground"]</code></pre><p>A couple of things to note here. Cloud Run expects your container to listen on port <code>8080</code> by default — that's why we're modifying the Apache configuration. I'm using <code>pdo_pgsql</code> because I connect to Cloud SQL PostgreSQL, but swap that for <code>pdo_mysql</code> if you're on MySQL.</p><h2 id="deploying-to-cloud-run">Deploying to Cloud Run</h2><p>With the Dockerfile ready, deploying is a single <code>gcloud</code> command. First, make sure you have the Google Cloud SDK installed and authenticated.</p><pre><code>gcloud run deploy my-laravel-app \
    --source . \
    --region africa-south1 \
    --allow-unauthenticated \
    --set-env-vars APP_KEY=base64:YOUR_APP_KEY_HERE \
    --set-env-vars APP_ENV=production \
    --set-env-vars LOG_CHANNEL=stderr \
    --set-env-vars DB_CONNECTION=pgsql \
    --set-env-vars DB_HOST=/cloudsql/PROJECT_ID:africa-south1:INSTANCE_NAME \
    --add-cloudsql-instances PROJECT_ID:africa-south1:INSTANCE_NAME \
    --memory 512Mi \
    --cpu 1 \
    --min-instances 0 \
    --max-instances 5</code></pre><p>The <code>--source .</code> flag tells Cloud Run to build the container image for you using Cloud Build — so you don't even need to push to Artifact Registry manually. Google handles the build and deployment in one step.</p><p>Notice the <code>--min-instances 0</code> — this is what enables scale-to-zero. For a staging environment or a low-traffic application, this keeps your costs minimal. For production, you might want to set <code>--min-instances 1</code> to avoid cold starts.</p><p>The <code>LOG_CHANNEL=stderr</code> setting is important. Cloud Run captures <code>stderr</code> output and sends it to Cloud Logging, so you get your Laravel logs in the Google Cloud Console without any additional configuration.</p><h2 id="connecting-to-cloud-sql">Connecting to Cloud SQL</h2><p>If you're using Cloud SQL — and I've written about <a href="https://sysadmin-journal.com/google-cloud-workload-identity-federation-a-guide-to-keyless-authentication-for-multi-cloud-environments/">scaling Laravel with Cloud SQL read replicas</a> before — Cloud Run has built-in support for connecting through the Cloud SQL Auth Proxy. The <code>--add-cloudsql-instances</code> flag in the deploy command sets this up automatically.</p><p>The connection happens over a Unix socket, which is why the <code>DB_HOST</code> is set to <code>/cloudsql/PROJECT_ID:REGION:INSTANCE_NAME</code> rather than an IP address. This is secure by default — no public IP required on your Cloud SQL instance.</p><h2 id="what-about-file-storage">What About File Storage?</h2><p>Laravel's default file storage driver writes to the local filesystem. That won't work on Cloud Run because the container filesystem is ephemeral — it gets wiped on every new deployment or instance scale event. For file uploads and storage, switch to Google Cloud Storage using the <code>league/flysystem-google-cloud-storage</code> package:</p><pre><code>composer require league/flysystem-google-cloud-storage</code></pre><p>Configure a <code>gcs</code> disk in your <code>config/filesystems.php</code> and set <code>FILESYSTEM_DISK=gcs</code> in your environment variables. Cloud Run's service account will handle authentication automatically if you've granted it the <code>Storage Object Admin</code> role — no API keys needed.</p><h2 id="things-to-keep-in-mind">Things to Keep in Mind</h2><p>Cloud Run is stateless. This means you cannot rely on the local filesystem for sessions or cache. Use <strong>Redis</strong> (via Memorystore) or <strong>database sessions</strong> instead. Similarly, Laravel's scheduler (<code>php artisan schedule:run</code>) doesn't work in Cloud Run's request-driven model. For scheduled tasks, pair Cloud Scheduler with Cloud Run by having the scheduler trigger an HTTP endpoint on your application.</p><p>Queue workers are another consideration. Cloud Run isn't designed for long-running processes, so running <code>php artisan queue:work</code> inside a Cloud Run container isn't ideal. Instead, use Cloud Tasks to dispatch jobs to a dedicated Cloud Run endpoint, or run your workers on a Compute Engine instance or GKE.</p><h2 id="wrapping-up">Wrapping Up</h2><p>Cloud Run sits in a sweet spot between the full control of a Compute Engine VM and the abstraction of a purely serverless function. For Laravel applications that don't need persistent background processes or filesystem state, it's an excellent deployment target — especially now that PHP 8.5 is fully supported.</p><p>I've been using it for a couple of internal tools and staging environments, and the cost savings alone from scale-to-zero make it worth exploring. If you're already on Google Cloud and deploying Laravel, it's worth giving Cloud Run a try on your next project.</p>]]></content:encoded>
        </item>
        <item>
            <title>How to change the default login redirect in Laravel 12 (The Simple Way)</title>
            <link>https://sysadmin-journal.com/how-to-change-the-default-login-redirect-in-laravel-12-the-simple-way</link>
            <guid isPermaLink="true">https://sysadmin-journal.com/how-to-change-the-default-login-redirect-in-laravel-12-the-simple-way</guid>
            <pubDate>Tue, 06 Jan 2026 14:21:48 +0000</pubDate>
            <dc:creator>Ish Sookun</dc:creator>
            <category>Laravel</category>
            <description>Stop digging through middleware! Discover the simplest way to change the default /dashboard login redirect in Laravel 12.x by tweaking a single line in your config/fortify.php file.</description>
            <content:encoded><![CDATA[<p>If you have recently spun up a new Laravel 12.x application using a starter kit (Livewire, React, etc), you are likely familiar with this flow: you log in successfully, and the application immediately redirects you to <code>/dashboard</code>.</p><p>While <code>/dashboard</code> is a sensible default for many SaaS applications, it isn't always what you need. Perhaps you are building an admin panel that lives at <code>/panel</code>, or maybe you are building a membership site or e-commerce store where the user should simply return to the homepage (<code>/</code>) after logging in.</p><p>If you dive into the official documentation, you might find yourself deep in <code>bootstrap/app.php</code> trying to customize the <code>auth</code> middleware logic. While that works, there is a much simpler configuration change that handles this in seconds.</p><h3 id="the-hard-way-middleware">The "Hard" Way: Middleware</h3><p>Typically, the documentation guides developers to intercept the request within the <code>bootstrap/app.php</code> file to handle redirection for guests and authenticated users. This involves defining closures and logic that can clutter your bootstrap file if you only need a simple path change.</p><h3 id="the-easy-way-config-configuration">The "Easy" Way: Config Configuration</h3><p>If your starter kit is powered by <a href="https://laravel.com/docs/12.x/fortify" rel="noreferrer"><strong>Laravel Fortify</strong></a> (which handles the backend authentication logic for kits like Jetstream), you don't need to touch your middleware or controllers. You can control this behavior directly from your configuration files.</p><p>Here is the one-line fix:</p><ol><li>Navigate to <strong><code>config/fortify.php</code></strong>.</li><li>Locate the <code>'home'</code> key (usually near the top of the file).</li><li>Change the value from <code>RouteServiceProvider::HOME</code> (or <code>'/dashboard'</code>) to your desired path.</li></ol><p>To redirect to the Homepage:</p><pre><code>'home' =&gt; '/',</code></pre><p>To redirect to a custom Admin Panel:</p><pre><code>'home' =&gt; '/panel',</code></pre><h3 id="why-this-works">Why this works</h3><p>Laravel Fortify uses this configuration value to determine where to send the user immediately after the authentication guard confirms their credentials. By changing it here, you ensure that the redirect is consistent across your application without having to write custom redirection logic in your controllers.</p><p>Don't overcomplicate your authentication flow. Before you start writing custom middleware logic in Laravel 12, check your <code>config/fortify.php</code> file. A simple string change is often all it takes to get your users exactly where they need to go.</p>]]></content:encoded>
        </item>
        <item>
            <title>Laravel Moris March Meetup</title>
            <link>https://sysadmin-journal.com/laravel-moris-march-meetup</link>
            <guid isPermaLink="true">https://sysadmin-journal.com/laravel-moris-march-meetup</guid>
            <pubDate>Sat, 29 Mar 2025 17:14:36 +0000</pubDate>
            <dc:creator>Ish Sookun</dc:creator>
            <category>Laravel</category>
            <description>Recently, the PHP community in Mauritius saw a revival thanks to the Laravel developers on the island. Laravel Moris has been active since a while now and the organisers are doing a great job at pulling together the PHP flock that has been working in silo for a long while.</description>
            <content:encoded><![CDATA[<p>Laravel Moris held a meetup today at Workshop17 in Vivéa Business Park, St. Pierre. I had a talk scheduled, themed on Laravel and FrankenPHP.</p><p>Meetup was planned at 10 a.m. I reached Les Fascines, Vivéa Business Park fifteen minutes earlier. As I arrived in the parking lot, I started reading the signage to look for directions for Workshop17. Just then, I saw Bruno and Nathan, both walking towards the building. I waived at them and we talked while walking towards the entrance.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sysadmin-journal.com/content/images/2025/03/laravel-moris-march-meetup-ravish-dussaruth.jpeg" class="kg-image" alt="" loading="lazy" width="1000" height="562" srcset="/content/images/size/w600/2025/03/laravel-moris-march-meetup-ravish-dussaruth.jpeg 600w, /content/images/2025/03/laravel-moris-march-meetup-ravish-dussaruth.jpeg 1000w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Ravish Dussaruth, Event host</span></figcaption></figure><p>Ravish Dussaruth was the event host (for the day). He welcomed everyone and gave an introduction about the <a href="https://laravel-moris.africa/" rel="noreferrer">Laravel Moris</a> community. He spoke about <a href="https://laracon.in/" rel="noreferrer">Laracon India</a> which he attended earlier this month along with other co-organisers of Laravel Moris. He thanked the two sponsors of today's meetup, <a href="https://viitorcloud.com/" rel="noreferrer">Viitorcloud</a> and <a href="https://nativephp.com/" rel="noreferrer">NativePHP</a>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sysadmin-journal.com/content/images/2025/03/laravel-moris-march-meetup-sponsors.png" class="kg-image" alt="Thanks to Viitorcloud and NativePHP for supporting the local community" loading="lazy" width="2000" height="400" srcset="/content/images/size/w600/2025/03/laravel-moris-march-meetup-sponsors.png 600w, /content/images/size/w1000/2025/03/laravel-moris-march-meetup-sponsors.png 1000w, /content/images/size/w1600/2025/03/laravel-moris-march-meetup-sponsors.png 1600w, /content/images/2025/03/laravel-moris-march-meetup-sponsors.png 2000w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Thanks to Viitorcloud and NativePHP for supporting the local community</span></figcaption></figure><p>Then, Ravish introduced today's first speaker, Percy Mamedy, who is also a co-organiser of Laravel Moris.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sysadmin-journal.com/content/images/2025/03/laravel-moris-march-meetup-percy-mamedy.jpeg" class="kg-image" alt="Percy Mamedy, Laravel Moris co-organiser, CTO at Assurdeal" loading="lazy" width="1000" height="562" srcset="/content/images/size/w600/2025/03/laravel-moris-march-meetup-percy-mamedy.jpeg 600w, /content/images/2025/03/laravel-moris-march-meetup-percy-mamedy.jpeg 1000w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Percy Mamedy, Laravel Moris co-organiser, CTO at Assurdeal</span></figcaption></figure><p>Percy spoke about the recent release of <a href="https://laravel.com/docs/12.x/starter-kits" rel="noreferrer">Laravel Starter Kits</a>. He highlighted the features of the three default starter kits, React, Vue and Livewire. E.g the React starter kit comes with Inertia.js pre-configured, it's built using the <a href="https://ui.shadcn.com/" rel="noreferrer">shadcn/ui</a> library, and comes with user authentication features, either using the built-in Laravel authentication (which most of us are familiar with) or WorkOS Authkit. I know nothing about WorkOS. Even Percy asked the attendees if anyone was familiar with WorkOS and could share thoughts on that but no one used it before.</p><p>Then, Percy did a quick demo of the starter kits, showing how easily and quickly one could adapt the layout with the different options available. Also, one could further customise the code if the default layout/style is not preferred.</p><p>Lastly, he mentioned that Laravel now allows the use of custom starter kits. Therefore, developers are not limited to starting a new project with the default Vue, React and Livewire starter kits, but one could pull a community based starter kit, say for example a Svelte starter kit and use it, one could build his/her own starter kit as well.</p><pre><code class="language- ">laravel new my-app --using=statamic/statamic</code></pre><p>The above command creates a new Laravel project using the Statamic starter-kit. During the discussion, as Percy's presentation ended, someone asked that it would be nice if there is a location where all starter kits could be published. I found a <a href="https://github.com/tnylea/laravel-new" rel="noreferrer">GitHub project</a> by Tony Lea which lists such starter kits. The one by Statamic seems to have garnered the most installs so far.</p><p>After Percy's presentation, Sanjivee Muthoora spoke about Viitorcloud.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sysadmin-journal.com/content/images/2025/03/laravel-moris-march-meetup-sanjiv-muthoora.jpeg" class="kg-image" alt="Sanjiv Muthoora, presenting projects by Viitorcloud" loading="lazy" width="2000" height="1125" srcset="/content/images/size/w600/2025/03/laravel-moris-march-meetup-sanjiv-muthoora.jpeg 600w, /content/images/size/w1000/2025/03/laravel-moris-march-meetup-sanjiv-muthoora.jpeg 1000w, /content/images/size/w1600/2025/03/laravel-moris-march-meetup-sanjiv-muthoora.jpeg 1600w, /content/images/2025/03/laravel-moris-march-meetup-sanjiv-muthoora.jpeg 2048w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Sanjivee Muthoora, presenting projects by Viitorcloud</span></figcaption></figure><p>He mentioned the participation of Viitorcloud at Laracon India and Laracon EU. He also shared information about the company, projects that they've delivered and some exciting projects that will be released soon.</p><p>I was the next speaker in line.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sysadmin-journal.com/content/images/2025/03/laravel-moris-march-meetup-ish-sookun.jpeg" class="kg-image" alt="Ish Sookun (me) presenting FrankenPHP, photo courtesy — Laravel Moris" loading="lazy" width="2000" height="1500" srcset="/content/images/size/w600/2025/03/laravel-moris-march-meetup-ish-sookun.jpeg 600w, /content/images/size/w1000/2025/03/laravel-moris-march-meetup-ish-sookun.jpeg 1000w, /content/images/size/w1600/2025/03/laravel-moris-march-meetup-ish-sookun.jpeg 1600w, /content/images/2025/03/laravel-moris-march-meetup-ish-sookun.jpeg 2048w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Ish Sookun (me) presenting FrankenPHP, photo courtesy — Laravel Moris</span></figcaption></figure><p>My presentation was titled, <em>"deploying Laravel with FrankenPHP".</em></p><p>I started with a problem statement — at La Sentinelle, for years we struggled to host news content locally. Recently, thanks to <a href="https://cloud.mu" rel="noreferrer">cloud.mu</a>, that has been possible. However, the Virtual Private Servers (VPS) do not provide us similar fast provisioning and auto-scaling features like those available from major cloud providers. In our quest to build something similar on top of the cloud.mu infra, we decided to experiment with Kubernetes — for future web projects.</p><p>I showed a few examples of Laravel based websites that we've developed at La Sentinelle, while mentioning which starter kit we used. Then, I mentioned the websites of the <a href="https://cloudnativemauritius.com" rel="noreferrer">Cloud Native Chapter of Mauritius</a> and <a href="https://meetup.mu" rel="noreferrer">meetup.mu</a> created by Alex Bissessur, both sites run Laravel. Lastly, I mentioned the <a href="https://conference.mscc.mu" rel="noreferrer">Developers Conference</a> website, which also runs Laravel.</p><p>Next, I explained the process of containerising a Laravel application using a <code>Containerfile</code> which I jokingly said I prefer instead of the other one that starts with D.</p><p>Bruno, confirmed that <code>podman</code> recognises <code>Containerfile</code> and that I would not require the <code>-f</code> option to specify the filename, but instead I could simply use the dot <code>.</code> symbol. Meaning, I could run the <code>podman</code> command as follows to build the container image.</p><pre><code>podman build -t 5plus:laravel .</code></pre><p>Once the image was built, which took about 17 seconds, I pushed the image to the GitHub's container repository. Then, I open my Kubernetes deployment YAML file to update the image name, and finally I applied the deployment file. We waited a few minutes for Kubernetes to deploy a pod with the new image and when it was done, I tested the web page. It worked.</p><p>I answered a few questions related to Kubernetes. I missed Alex during the Q&amp;A time, as his k8s knowledge was required to answer questions regarding monitoring of deployments and how to handle failed deployments. Alex could not make it to this month's meetup, but I'm sure in a future meetup, he will be able to assist anyone wishing to learn more about managing deployments.</p><p>The next presenter was remote — <a href="https://x.com/sarthaksavvy" rel="noreferrer">Sarthak Shrivastava</a> from India. Sarthak is a Software Engineer at Pfizer and is the founder of <a href="https://bitfumes.com/" rel="noreferrer">Bitfumes</a>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sysadmin-journal.com/content/images/2025/03/laravel-moris-march-meetup-sarthak-sharivastava.jpeg" class="kg-image" alt="Sarthak Shrivastava, remote presentation" loading="lazy" width="1000" height="562" srcset="/content/images/size/w600/2025/03/laravel-moris-march-meetup-sarthak-sharivastava.jpeg 600w, /content/images/2025/03/laravel-moris-march-meetup-sarthak-sharivastava.jpeg 1000w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Sarthak Shrivastava, remote presentation</span></figcaption></figure><p>Sarthak spoke about Vibe Coding. He gave a bit of background on conversing with AI. He explained about prompt engineering — not giving too many tasks in one prompt and try to break down the tasks into several prompts with concise instructions. He also mentioned that sometimes people personalise the AI by saying something like "you are a Laravel developer with 10 years of experience" but Sarthak advises to use "you have 10 years of programming experience" instead, in order to broaden the expertise area rather than keeping it within the scope of Laravel.</p><p>He did a demo using <a href="https://www.cursor.com/" rel="noreferrer">Cursor</a> — the AI code editor that has been much in the news, since Vibe Coding has gone viral. It was a nice talk, we had a exchange of ideas on comparing Cursor with VS Code + GitHub Copilot.</p><p>We had lunch break after Sarthak's talk and demo.</p><p>The last talk was also remote, and a short one, by <a href="https://x.com/simonhamp" rel="noreferrer">Simon Hamp</a>, the creator of NativePHP — the cool stuff that allows you to build desktop and mobile applications using PHP. 🤯</p><figure class="kg-card kg-image-card"><img src="https://sysadmin-journal.com/content/images/2025/03/laravel-moris-march-meetup-simon-hamp.jpeg" class="kg-image" alt="" loading="lazy" width="1000" height="562" srcset="/content/images/size/w600/2025/03/laravel-moris-march-meetup-simon-hamp.jpeg 600w, /content/images/2025/03/laravel-moris-march-meetup-simon-hamp.jpeg 1000w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sysadmin-journal.com/content/images/2025/03/laravel-moris-march-meetup-simon-hamp-remote-talk.jpeg" class="kg-image" alt="Simon Hamp, Creator &amp; Maintainer of NativePHP" loading="lazy" width="1000" height="562" srcset="/content/images/size/w600/2025/03/laravel-moris-march-meetup-simon-hamp-remote-talk.jpeg 600w, /content/images/2025/03/laravel-moris-march-meetup-simon-hamp-remote-talk.jpeg 1000w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Simon Hamp, Creator &amp; Maintainer of NativePHP</span></figcaption></figure><p>Simon shared his motivation behind creating NativePHP. He explained how awesome things that can be done with it and invited us to try to build applications with NativePHP. He explained that the idea of putting a license for using NativePHP mobile is solely to generate revenue that can sustain the continuous development of the project. He also explained about the Early Access Program (EAP) for NativePHP mobile.</p><p>As we reached 1.30 p.m., it was almost time to end meetup. The last fifteen minutes was spent with a fast Q&amp;A with some of the speakers that intervened, i.e Percy, Sarthak and myself, in a panel style. We tried our best to answer the questions. 🙏</p><p>The meetup was attended by about 15 people. It was time well-spent with the Laravel community of Mauritius.</p>]]></content:encoded>
        </item>
        <item>
            <title>Laravel Livewire table pagination scroll behaviour</title>
            <link>https://sysadmin-journal.com/laravel-livewire-table-pagination-scroll-behaviour</link>
            <guid isPermaLink="true">https://sysadmin-journal.com/laravel-livewire-table-pagination-scroll-behaviour</guid>
            <pubDate>Sat, 15 Jun 2024 10:30:28 +0000</pubDate>
            <dc:creator>Ish Sookun</dc:creator>
            <category>Laravel</category>
            <description>The docs page for Livewire 3.x has a section for pagination. It mentions the default behaviours and how to change those. As per the docs, the default behaviour of the paginator is to scroll to the top of the page after every page change (which occurs when clicking the pagination buttons).</description>
            <content:encoded><![CDATA[<p>Recently, I was working on a Laravel Livewire table and I noticed a rather "annoying" behaviour when click on the pagination buttons. There were a bunch of paragraphs above the table. So, you had to scroll down the page to see the table. Then, when you clicked on the pagination buttons, the page would instantly scroll to the top. Rather annoying! This would occur on every pagination button click.</p><p>It occurred with both the <code>paginate()</code> or <code>simplePaginate()</code> methods.</p><p>After a lot of unsuccessful search on the internet, I finally found the solution at the obvious place — <a href="https://livewire.laravel.com/docs/pagination" rel="noreferrer">Laravel Livewire official documentation</a>.</p><p>The docs page for Livewire 3.x has a section for pagination. It mentions the default behaviours and how to change those. As per the docs, the <a href="https://livewire.laravel.com/docs/pagination#customizing-scroll-behavior" rel="noreferrer">default behaviour</a> of the paginator is to scroll to the top of the page after every page change (which occurs when clicking the pagination buttons). In order to disable this behaviour, you should pass <code>false</code> to the <code>scrollTo</code> parameter of the <code>links()</code> method.</p><pre><code>{{ $posts-&gt;links(data: ['scrollTo' =&gt; false]) }}</code></pre><p>The docs provide more information about customising the paginator. Now that I know this exists, my Livewire tables in the future would be more customised. 😊</p>]]></content:encoded>
        </item>
        <item>
            <title>A summary of my presentation at DevFest Mauritius 2023, on PHP, SUSE Base Container Image and Google Kubernetes Engine</title>
            <link>https://sysadmin-journal.com/gdg-devfest2023-mauritius</link>
            <guid isPermaLink="true">https://sysadmin-journal.com/gdg-devfest2023-mauritius</guid>
            <pubDate>Mon, 30 Oct 2023 19:24:00 +0000</pubDate>
            <dc:creator>Ish Sookun</dc:creator>
            <category>DevFest</category>
            <category>Conference</category>
            <category>Kubernetes</category>
            <category>Laravel</category>
            <category>Linux</category>
            <description>GDG DevFest Mauritius is the annual, community-led “Developers Festival” organized by GDG Mauritius (Google Developer Group). It’s a one‑day, multi-track event designed for developers and tech enthusiasts to dive into Google’s technology stack while connecting with peers in the local ecosystem.</description>
            <content:encoded><![CDATA[
<!--kg-card-begin: html-->
<div class="p-4 bg-teal-600 text-white text-md">
  This article is a re-production from my <a href="https://www.linkedin.com/pulse/summary-my-presentation-devfest-mauritius-2023-php-suse-ish-sookun-txc9f/" class="underline text-white hover:text-gray-200" target="_blank">LinkedIn article</a> with the same title.
</div>
<!--kg-card-end: html-->
<p>After many years, I participated in an event organised in collaboration with the University of Mauritius. Ten years ago, around this time of the year the Linux User Group of Mauritius and the UoM Computer Club (2013) organised a <a href="https://legacy.hacklog.in/post/linuxfest-2013-highlights/" rel="noopener noreferrer">Linux Festival</a> at the Paul Octave Wiehe Auditorium. Last Saturday's Google Developers Festival (DevFest) 2023, being held on the campus of the University of Mauritius, brought back memories of those days. It also reminded me that it's been a decade since I am actively contributing to the tech community. 🎊🤓</p><p><em>Some happy tears flow down the cheek. Sniff!</em></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sysadmin-journal.com/content/images/2025/07/1698604861977.jpeg" class="kg-image" alt="Presenting Laravel/PHP, SUSE Base Container Image and Google Kubernetes Engine at DevFest 2023. Photo courtesy of Arwin Neil Baichoo." loading="lazy" width="960" height="720" srcset="/content/images/size/w600/2025/07/1698604861977.jpeg 600w, /content/images/2025/07/1698604861977.jpeg 960w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Presenting Laravel/PHP, SUSE Base Container Image and Google Kubernetes Engine at DevFest 2023. Photo courtesy of Arwin Neil Baichoo.</span></figcaption></figure><p>Okay, let's talk about DevFest 2023. DevFest is an annual tech conference organised globally by the Google Developer Groups (GDG) community. This year marked the 5th edition of DevFest Mauritius. It was hosted by GDG Mauritius and the University of Mauritius (UoM). The Google Student Developer Clubs of UoM, University of Technology, Polytechnics Mauritius and the African Leadership College helped in spreading the word.</p><p>Registration for the event was done through the <a href="https://gdg.community.dev/gdg-mauritius/" rel="noopener noreferrer">GDG Mauritius</a> chapter page on the Google Developer Groups Bevy platform, while information about the event, the agenda and the speakers was also available at <a href="http://devfest.mscc.mu/" rel="noopener noreferrer">devfest.mscc.mu</a>.</p><p>We had 20 speakers from different tech backgrounds — web development, mobile application development and systems/cloud engineering.</p><p>My presentation was scheduled at 11:30 a.m. in the G2 room of the Faculty of Law &amp; Management. I started the presentation sharp on time to be able to stay both on track and on time, as for the next 45 mins, I had planned a whole journey of writing code to deploying the same on a cluster of servers.</p><figure class="kg-card kg-image-card"><img src="https://sysadmin-journal.com/content/images/2025/07/1698603509640.png" class="kg-image" alt="" loading="lazy" width="1488" height="837" srcset="/content/images/size/w600/2025/07/1698603509640.png 600w, /content/images/size/w1000/2025/07/1698603509640.png 1000w, /content/images/2025/07/1698603509640.png 1488w" sizes="(min-width: 720px) 720px"></figure><p>PHP is still relevant in 2023. It still powers a lot of websites on the Internet. Even Facebook started on PHP and later created the <a href="https://hhvm.com/" rel="noopener noreferrer">HipHop Virtual Machine (HHVM)</a> to compile PHP source code to HipHop bytecode for faster execution and then they created the <a href="https://hacklang.org/" rel="noopener noreferrer">Hack programming language</a>.</p><p>I started the presentation by talking about PHP.</p><p>If you are just starting with PHP development, I suggest that you closely follow the works of a PHP framework, like Laravel or Symfony. I use Laravel a lot — in fact most of my web related work is now on <a href="https://laravel.com/" rel="noopener noreferrer">Laravel</a>. During the presentation I mentioned how <a href="http://lexpress.mu/" rel="noopener noreferrer">lexpress.mu</a> moved from Drupal to Laravel.</p><p>My next slide had a few commands needed to create a Laravel project and to run it locally (assuming that PHP and composer are already installed on that machine).</p><figure class="kg-card kg-image-card"><img src="https://sysadmin-journal.com/content/images/2025/07/1698604459198.png" class="kg-image" alt="" loading="lazy" width="1488" height="837" srcset="/content/images/size/w600/2025/07/1698604459198.png 600w, /content/images/size/w1000/2025/07/1698604459198.png 1000w, /content/images/2025/07/1698604459198.png 1488w" sizes="(min-width: 720px) 720px"></figure><p>Now, that we had a codebase and we made our desired modifications to the Laravel code, it was time that we thought about packaging it and shipping it to the cloud. The easy way — containers!</p><figure class="kg-card kg-image-card"><img src="https://sysadmin-journal.com/content/images/2025/07/1698605629685.png" class="kg-image" alt="" loading="lazy" width="1488" height="837" srcset="/content/images/size/w600/2025/07/1698605629685.png 600w, /content/images/size/w1000/2025/07/1698605629685.png 1000w, /content/images/2025/07/1698605629685.png 1488w" sizes="(min-width: 720px) 720px"></figure><p>SUSE Base Container Image (SUSE BCI) enters the scene. We can of course find plenty of PHP based containers to ship the code, then why SUSE BCI? The short anwser is compliance. Very often if you are working for a big company, there are rules to use software that have enterprise support. SUSE BCIs are enterprise-ready container images based on the SUSE Linux Enterprise Server (SLES). One can purchase a support subscription for the container or inherit an existing subscription from a host SUSE Linux Enterprise Server.</p><p>I talked about the Base Images and the Language Container Images. For our need to ship the Laravel codebase, we looked at the three SUSE BCIs that support PHP.</p><figure class="kg-card kg-image-card"><img src="https://sysadmin-journal.com/content/images/2025/07/1698605796663.png" class="kg-image" alt="" loading="lazy" width="1488" height="837" srcset="/content/images/size/w600/2025/07/1698605796663.png 600w, /content/images/size/w1000/2025/07/1698605796663.png 1000w, /content/images/2025/07/1698605796663.png 1488w" sizes="(min-width: 720px) 720px"></figure><p>The ideal candidate was the SUSE BCI PHP-Apache 8 image. Our Laravel code is actually this year's DevFest Mauritius website. We do not require a database. The conference schedule and speakers details are pulled from a <a href="http://sessionize.com/" rel="noopener noreferrer">Sessionize.com</a> API and kept as JSON locally. Therefore, a single container to run the PHP code and serve the HTTP content would be fine.</p><p>I spoke about the three SUSE BCIs for PHP and possible use cases on different types of PHP scripts or applications we may run.</p><p>Okay, it's good that we have a container to run PHP code but it's not great, yet — because it cannot run "our" PHP code. Laravel 10 requires PHP version 8.2 to run whereas the SUSE BCI has PHP version 8.0.30 as latest version.</p><figure class="kg-card kg-image-card"><img src="https://sysadmin-journal.com/content/images/2025/07/1698606527692.png" class="kg-image" alt="" loading="lazy" width="1488" height="837" srcset="/content/images/size/w600/2025/07/1698606527692.png 600w, /content/images/size/w1000/2025/07/1698606527692.png 1000w, /content/images/2025/07/1698606527692.png 1488w" sizes="(min-width: 720px) 720px"></figure><p>Most Enterprise Linux distributions support packages for as long as security fixes remain available for the package. That is the case with SLES and PHP 8 here. The latest version of PHP available from the official SLE_BCI repo is PHP version 8.0.30 which will continue to receive security fixes until the end of November this year, then the package will be upgraded to version 8.1.x which will receive security fixes until November 2024.</p><p>Then, how can we use the SUSE Linux Enterprise container but with PHP version 8.2?</p><p>Comes into the scene, SUSE's own <a href="https://openbuildservice.org/" rel="noopener noreferrer">Open Build Service</a>.</p><figure class="kg-card kg-image-card"><img src="https://sysadmin-journal.com/content/images/2025/07/obs.png" class="kg-image" alt="" loading="lazy" width="1488" height="837" srcset="/content/images/size/w600/2025/07/obs.png 600w, /content/images/size/w1000/2025/07/obs.png 1000w, /content/images/2025/07/obs.png 1488w" sizes="(min-width: 720px) 720px"></figure><p>I explained how Open Build Service (OBS) allows one to compile software and package the latter for different Linux distributions and different CPU architectures. Then, I mentioned <a href="http://build.opensuse.org/" rel="noopener noreferrer">build.opensuse.org</a> where SUSE upstream projects reside. Recently, the Linux Foundation decided to <a href="https://www.suse.com/c/suse-open-build-service-now-adopted-by-the-kubernetes-to-generate-its-official-packages/" rel="noopener noreferrer">build Kubernetes packages using OBS</a> too. I talked about how openSUSE Leap and SUSE Linux Enterprise share a 1:1 binary compatible codebase.</p><p>One could build PHP v8.2.12 packages using <a href="http://build.opensuse.org/" rel="noopener noreferrer">build.opensuse.org</a> but... there is actually no need — because v8.2.12 is already built for SLE 15 SP5. 😎 We can simply add the OBS repo to our SLE BCI Apache-PHP container and install the latest version of PHP.</p><figure class="kg-card kg-image-card"><img src="https://sysadmin-journal.com/content/images/2025/07/1698612144212.png" class="kg-image" alt="" loading="lazy" width="1488" height="837" srcset="/content/images/size/w600/2025/07/1698612144212.png 600w, /content/images/size/w1000/2025/07/1698612144212.png 1000w, /content/images/2025/07/1698612144212.png 1488w" sizes="(min-width: 720px) 720px"></figure><p>Huh! So, by this time we have a codebase, we have chosen a BCI and we know how to get the latest version of PHP running which is required for our application (i.e the website of DevFest Mauritius 2023). What's next? We need to build a container image that will hold our codebase and be ready for shipping.</p><p>So... Let's build it!</p><p>Before talking about building containers though, I mentioned that I don't like the idea of simply copying Dockerfiles from the Internet and start using. Writing a Dockerfile is not difficult and a lot of times it requires just a few lines. It also helps us keep things clean and we know what we are doing.</p><p>Let's write a Dockerfile then.</p><figure class="kg-card kg-image-card"><img src="https://sysadmin-journal.com/content/images/2025/07/dockerfile.gif" class="kg-image" alt="" loading="lazy" width="1080" height="608" srcset="/content/images/size/w600/2025/07/dockerfile.gif 600w, /content/images/size/w1000/2025/07/dockerfile.gif 1000w, /content/images/2025/07/dockerfile.gif 1080w" sizes="(min-width: 720px) 720px"></figure><p>During the presentation, I explained what each line does. Especially, why I chained the RUN commands in one line instead of multiple RUN commands. Each RUN command creates an OverlayFS layer and takes up a little more space. In this example, it would have taken an additional 8MB if we had used multiple RUN commands for every CLI command specified.</p><pre><code>FROM registry.suse.com/bci/php-apache:8</code></pre><p>In the first line, we pull the SUSE BCI PHP-Apache 8 image. Then, we copy our project directory inside the container image at a specific path which we have specified in an Apache configuration. I talked briefly about Apache VirtualHosts.</p><pre><code>COPY ./devfest2023 /srv/www/vhosts/devfest2023
COPY ./devfest2023.conf /etc/apache2/vhosts.d/devfest2023.conf</code></pre><p>Next, we copy a "repo" configuration file that contains information about the OBS repository.</p><pre><code>COPY ./obs_php.repo /etc/zypp/repos.d</code></pre><p>The content of the .repo file is available from the PHP package project on <a href="http://build.opensuse.org/" rel="noopener noreferrer">build.opensuse.org</a>.</p><p>We run the zypper ref command to update the repo database. We update the packages with the --allow-vendor-change option. Without this option, it will not upgrade PHP because the currently installed PHP package by vendor SUSE is the highest version available. By allowing vendor change, the package will be upgraded using newer packages from the OBS repository.</p><pre><code>RUN zypper ref; zypper up -y --allow-vendor-change; \
zypper in -y php8-tokenizer php8-iconv php8-intl php8-bcmath \
php8-bz2 php8-ctype php8-gd php8-posix php8-readline</code></pre><p>We install a few other PHP libraries that will be required by our Laravel application.</p><p>Laravel writes to a log file stored at the storage/laravel.log path. Therefore, ownership of the directory is changed to the user wwwrun which is the user that owns the Apache child processes.</p><pre><code>chown -R wwwrun:wwwrun /srv/www/vhosts/devfest2023; \</code></pre><p>We enable the mod_rewrite module in Apache because we have a Rewrite Rule in our Apache configuration that forwards all requests to the index.php file.</p><pre><code>a2enmod rewrite</code></pre><p>Lastly, we make the container reachable on port 80.</p><pre><code>EXPOSE 80</code></pre><p>Our Dockerfile is ready. We can build the container image.</p><figure class="kg-card kg-image-card"><img src="https://sysadmin-journal.com/content/images/2025/07/1698608690191.png" class="kg-image" alt="" loading="lazy" width="1488" height="837" srcset="/content/images/size/w600/2025/07/1698608690191.png 600w, /content/images/size/w1000/2025/07/1698608690191.png 1000w, /content/images/2025/07/1698608690191.png 1488w" sizes="(min-width: 720px) 720px"></figure><p>I explained what each of the options does in the docker build command. After building the image, we can run a container locally to test the application.</p><pre><code>docker run —-rm -p 8080:80 devfest:2023</code></pre><p>Once again, I explained what each of the option in the above command does.</p><p>So, we've built a container image successfully, we've tested our application running inside a container, what do we do next? Deploy to Google Kubernetes Engine (GKE)? Not, yet. We need to push this container image to a registry, from which GKE will be able to pull and deploy.</p><p>Hereon, we started talking about the <a href="https://cloud.google.com/" rel="noopener noreferrer">Google Cloud Platform</a>. We needed to enable two services on GCP before we can ship a container and deploy our application. The services are:</p><ul><li>Artifact Registry API</li><li>Kubernetes Engine API</li></ul><p>I explained that previously we would use the Container Registry API but that was only limited to Docker container images. The Artifact Registry can hold repos for container images, npm packages, python, etc.</p><figure class="kg-card kg-image-card"><img src="https://sysadmin-journal.com/content/images/2025/07/1698609219546.png" class="kg-image" alt="" loading="lazy" width="1488" height="837" srcset="/content/images/size/w600/2025/07/1698609219546.png 600w, /content/images/size/w1000/2025/07/1698609219546.png 1000w, /content/images/2025/07/1698609219546.png 1488w" sizes="(min-width: 720px) 720px"></figure><p>We created a repository in the Artifact Registry, we specified the format as Docker and we selected a region. We discussed about this choice (i.e region) for a while. My usual trick for obtaining the best latency to a "region" is to understand how our submarine fiber cables connect us to the rest of the world. Since, the SAFE/SAT-3/WASC submarine cable connects us to the west side of the European continent, for this example we chose the europe-west1 region, which is in Belgium. Not too far from the landing point in Portugal? 🤔 Anyway, let's continue...</p><figure class="kg-card kg-image-card"><img src="https://sysadmin-journal.com/content/images/2025/07/1698609615679.png" class="kg-image" alt="" loading="lazy" width="1488" height="837" srcset="/content/images/size/w600/2025/07/1698609615679.png 600w, /content/images/size/w1000/2025/07/1698609615679.png 1000w, /content/images/2025/07/1698609615679.png 1488w" sizes="(min-width: 720px) 720px"></figure><p>After creating the repository, the GCP console redirects to the repository details page. I encircled the path which we need when pushing the container image to the registry.</p><p>Oh... wait. Before pushing our container image to the Google Artifact Registry we need to setup authentication for Docker. Read the instructions <a href="https://cloud.google.com/artifact-registry/docs/docker/authentication" rel="noopener noreferrer">here</a>. During the presentation I did not elaborate on the Docker/GCP authentication part as it is purely textbook instruction.</p><p>We're almost there. We have built our container, we have set up our repository on Google Cloud, so now let's do the next step.</p><figure class="kg-card kg-image-card"><img src="https://sysadmin-journal.com/content/images/2025/07/1698609983709.png" class="kg-image" alt="" loading="lazy" width="1488" height="837" srcset="/content/images/size/w600/2025/07/1698609983709.png 600w, /content/images/size/w1000/2025/07/1698609983709.png 1000w, /content/images/2025/07/1698609983709.png 1488w" sizes="(min-width: 720px) 720px"></figure><p>We tag the local image devfest:2023 (which we built earlier) using the path we saw on the repository page. I explained each item in the command for clarity.</p><p>Then, we run:</p><pre><code>docker push europe-west1-docker.pkg.dev/devfest2023-403313/mscc/devfest:2023</code></pre><p>You can see the progress as each layer is being copied to the registry. When completed, refresh the registry page on the cloud console.</p><figure class="kg-card kg-image-card"><img src="https://sysadmin-journal.com/content/images/2025/07/1698610296926.png" class="kg-image" alt="" loading="lazy" width="1488" height="837" srcset="/content/images/size/w600/2025/07/1698610296926.png 600w, /content/images/size/w1000/2025/07/1698610296926.png 1000w, /content/images/2025/07/1698610296926.png 1488w" sizes="(min-width: 720px) 720px"></figure><p>Hereon, we started talking about Kubernetes and its complexity. However, Google (and other cloud providers) offer a Managed Kubernetes Service. Managed meaning — the implementation and related complexities are obsfuscated. Thus, as a developer you should be able to deploy your application in a cluster with minimal effort. That's exactly what Google Kubernetes Engine is about.</p><figure class="kg-card kg-image-card"><img src="https://sysadmin-journal.com/content/images/2025/07/1698610486453.png" class="kg-image" alt="" loading="lazy" width="1488" height="837" srcset="/content/images/size/w600/2025/07/1698610486453.png 600w, /content/images/size/w1000/2025/07/1698610486453.png 1000w, /content/images/2025/07/1698610486453.png 1488w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://sysadmin-journal.com/content/images/2025/07/1698610501133.png" class="kg-image" alt="" loading="lazy" width="1488" height="837" srcset="/content/images/size/w600/2025/07/1698610501133.png 600w, /content/images/size/w1000/2025/07/1698610501133.png 1000w, /content/images/2025/07/1698610501133.png 1488w" sizes="(min-width: 720px) 720px"></figure><p>You click on the three dots and select "Deploy to GKE".</p><figure class="kg-card kg-image-card"><img src="https://sysadmin-journal.com/content/images/2025/07/1698610551496.png" class="kg-image" alt="" loading="lazy" width="1488" height="837" srcset="/content/images/size/w600/2025/07/1698610551496.png 600w, /content/images/size/w1000/2025/07/1698610551496.png 1000w, /content/images/2025/07/1698610551496.png 1488w" sizes="(min-width: 720px) 720px"></figure><p>The first option is to select a container, but here the devfest:2023 container is pre-selected. You can add environment variables which you usually do through the .env file of a Laravel application. Since, we are not using a database or require any other specific info to pass on, we can skip this part.</p><figure class="kg-card kg-image-card"><img src="https://sysadmin-journal.com/content/images/2025/07/1698610679358.png" class="kg-image" alt="" loading="lazy" width="1488" height="837" srcset="/content/images/size/w600/2025/07/1698610679358.png 600w, /content/images/size/w1000/2025/07/1698610679358.png 1000w, /content/images/2025/07/1698610679358.png 1488w" sizes="(min-width: 720px) 720px"></figure><p>GKE creates a deployment configuration which defines the state of the cluster. It uses defaults here, e.g the replicas (i.e no. of nodes in the cluster) to 3. All of this information can viewed in the YAML file which is accessible from the page.</p><figure class="kg-card kg-image-card"><img src="https://sysadmin-journal.com/content/images/2025/07/1698610816292.png" class="kg-image" alt="" loading="lazy" width="1488" height="837" srcset="/content/images/size/w600/2025/07/1698610816292.png 600w, /content/images/size/w1000/2025/07/1698610816292.png 1000w, /content/images/2025/07/1698610816292.png 1488w" sizes="(min-width: 720px) 720px"></figure><p>The YAML file is read-only at this point. We cannot edit the deployment configuration but we can do so once the cluster is created. Then, we can edit the YAML config to adjust it to our needs or use other "buttons" in the console to scale the cluster up/down, horizontally or vertically.</p><p>After the configuration part, the last step is to select whether we want to create a service to expose the cluster. Since, we want our application to be available on the Internet, we expose the cluster on port 80.</p><figure class="kg-card kg-image-card"><img src="https://sysadmin-journal.com/content/images/2025/07/1698611005292.png" class="kg-image" alt="" loading="lazy" width="1488" height="837" srcset="/content/images/size/w600/2025/07/1698611005292.png 600w, /content/images/size/w1000/2025/07/1698611005292.png 1000w, /content/images/2025/07/1698611005292.png 1488w" sizes="(min-width: 720px) 720px"></figure><p>After we hit "DEPLOY", GKE starts building the cluster.</p><figure class="kg-card kg-image-card"><img src="https://sysadmin-journal.com/content/images/2025/07/1698611048564.png" class="kg-image" alt="" loading="lazy" width="1488" height="837" srcset="/content/images/size/w600/2025/07/1698611048564.png 600w, /content/images/size/w1000/2025/07/1698611048564.png 1000w, /content/images/2025/07/1698611048564.png 1488w" sizes="(min-width: 720px) 720px"></figure><p>For this example, the cluster was ready in less than 5 mins.</p><figure class="kg-card kg-image-card"><img src="https://sysadmin-journal.com/content/images/2025/07/1698611089697.png" class="kg-image" alt="" loading="lazy" width="1488" height="837" srcset="/content/images/size/w600/2025/07/1698611089697.png 600w, /content/images/size/w1000/2025/07/1698611089697.png 1000w, /content/images/2025/07/1698611089697.png 1488w" sizes="(min-width: 720px) 720px"></figure><p>Once the cluster is ready, the deployment details page will display information regarding the availability and health of the cluster nodes. At the bottom of the page, the <strong>endpoint</strong> in the Expose services show the Public IP Address for the deployment. Click on that and you can access your application. In our case, we were able to see the DevFest Mauritius 2023 site hosted on the IP address.</p><figure class="kg-card kg-image-card"><img src="https://sysadmin-journal.com/content/images/2025/07/1698611292237.png" class="kg-image" alt="" loading="lazy" width="1488" height="837" srcset="/content/images/size/w600/2025/07/1698611292237.png 600w, /content/images/size/w1000/2025/07/1698611292237.png 1000w, /content/images/2025/07/1698611292237.png 1488w" sizes="(min-width: 720px) 720px"></figure><p>That was my share of contribution to DevFest Mauritius 2023, as speaker this year. I hope everybody who attended the session enjoyed it and learned at least a thing or two. 😊</p>]]></content:encoded>
        </item>
        <item>
            <title>Laravel discontinues official ties with certification platform</title>
            <link>https://sysadmin-journal.com/laravel-discontinues-official-ties-with-certification-platform</link>
            <guid isPermaLink="true">https://sysadmin-journal.com/laravel-discontinues-official-ties-with-certification-platform</guid>
            <pubDate>Mon, 19 Dec 2022 07:52:20 +0000</pubDate>
            <dc:creator>Ish Sookun</dc:creator>
            <category>Laravel</category>
            <description>Laravel is an open source PHP framework created by Taylor Otwell. It is popular for creating web applications. Laravel has an elegant syntax and it very well documented.</description>
            <content:encoded><![CDATA[<p>Until now, many developers who sought a certification to prove their Laravel development knowledge turned to <strong><u>certification.laravel.com</u></strong>. That certification platform, although it operated under the laravel.com domain, it was not part of the core Laravel ecosystem. Meaning it was not managed by the very people who developed Laravel and its first-party packages.</p><p>Yesterday, someone tweeted and complained that he sent two tickets to the certification platform with no response.</p><!--kg-card-begin: html--><center>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Hello <a href="https://twitter.com/taylorotwell?ref_src=twsrc%5Etfw">@taylorotwell</a> ,<a href="https://t.co/HQ93h0A4sB">https://t.co/HQ93h0A4sB</a> still working? I sent two tickets and a message to Twitter, but no response 🤔.</p>&mdash; Vũ. (@phongvu_811) <a href="https://twitter.com/phongvu_811/status/1604523880676458496?ref_src=twsrc%5Etfw">December 18, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center><!--kg-card-end: html--><p>Taylor Otwell, the creator of Laravel responded in that conversation thread and confirmed that they are breaking ties with the certification platform.</p><!--kg-card-begin: html--><center>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">We are going to be discontinuing official ties between Laravel and that platform</p>&mdash; Taylor Otwell 🪐 (@taylorotwell) <a href="https://twitter.com/taylorotwell/status/1604546472447545345?ref_src=twsrc%5Etfw">December 18, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center><!--kg-card-end: html--><p>Taylor's dissatisfaction with the way the certification platform was being managed was very apparent in the tweet that followed.</p><!--kg-card-begin: html--><center>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">It means I am not happy with the way it has been run. At all.</p>&mdash; Taylor Otwell 🪐 (@taylorotwell) <a href="https://twitter.com/taylorotwell/status/1604585343445082113?ref_src=twsrc%5Etfw">December 18, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</center><!--kg-card-end: html--><p>The <u>certification.laravel.com</u> sub-domain now redirects to the project's homepage while returning an HTTP 302 status code.</p><pre><code>$ curl -I https://certification.laravel.com
HTTP/2 302 
date: Mon, 19 Dec 2022 07:38:57 GMT
location: https://laravel.com
cache-control: private, max-age=0, no-store, no-cache, must-revalidate, post-check=0, pre-check=0
expires: Thu, 01 Jan 1970 00:00:01 GMT
server: cloudflare
cf-ray: 77be7b4ebb53cb7b-MBA</code></pre><p>The HTTP 302 status code indicates that it is a <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/302">temporary redirection</a>.</p>]]></content:encoded>
        </item>
        <item>
            <title>Containers — why do we need multi-stage builds?</title>
            <link>https://sysadmin-journal.com/containers-why-do-we-need-multi-stage-builds</link>
            <guid isPermaLink="true">https://sysadmin-journal.com/containers-why-do-we-need-multi-stage-builds</guid>
            <pubDate>Sat, 17 Dec 2022 15:27:02 +0000</pubDate>
            <dc:creator>Ish Sookun</dc:creator>
            <category>Kubernetes</category>
            <category>Laravel</category>
            <category>Linux</category>
            <description>Docker is a platform designed to help developers build, share, and run modern applications. Docker Inc. was founded by Kamel Founadi, Solomon Hykes, and Sebastien Pahl in 2010. The company released Docker as an open-source software in 2013.</description>
            <content:encoded><![CDATA[<p>Last week, during my <a href="https://sysadmin-journal.com/google-devfest-2022-mauritius/">talk about Laravel &amp; Kubernetes</a> at the DevFest 2022, I built a containerised Laravel application using Docker and deployed it on the Google Kubernetes Engine (GKE). I briefly touched on the the multi-stage build process but did not provide a thorough explanation on why it is needed.</p><pre><code>FROM composer:latest AS build
WORKDIR /app
COPY . /app
RUN composer install --prefer-dist --no-dev --optimize-autoloader --no-interaction

FROM php:8.2-apache-bullseye AS production

ENV APP_ENV=production
ENV APP_DEBUG=false

RUN docker-php-ext-configure opcache --enable-opcache &amp;&amp; \
    docker-php-ext-install pdo pdo_mysql
RUN pecl install redis &amp;&amp; docker-php-ext-enable redis

COPY --from=build /app /app
COPY vhost.conf /etc/apache2/sites-available/000-default.conf
COPY .env.prod /app/.env

RUN cd /app &amp;&amp; php artisan config:cache &amp;&amp; \
    php artisan route:cache &amp;&amp; \
    chmod 777 -R /app/storage/ &amp;&amp; \
    chown -R www-data:www-data /app/ &amp;&amp; \
    a2enmod rewrite</code></pre><p>I used the above Dockerfile to build the Laravel container. There are two stages in this build process —</p><ul><li>First, a <code>composer:latest</code> container is used to install the project dependencies.</li><li>Then, a <code>php:8.2-apache-bullseye</code> container is used to run the Laravel application in production.</li></ul><p>To be honest, I should have added one more build stage to use NPM to compile the front-end stack... but... well, to better understand the reasons for multi-stage builds, let us look at something simpler.</p><pre><code class="language-Rust">fn main() {
    println!("Namaste, world! 🙏");
}</code></pre><p>The above Rust code does nothing fancy, it just prints "Namaste, world!" with the folded hands emoji, to the terminal. We could pull a Rust container image, e.g <code>rust:1.66.0-alpine3.17</code> to build and then run the application. It would work, right?</p><p>The <code>rust:1.66.0-alpine3.17</code> container image is 787MB in size. Would you want to deploy a small binary along with a 100 times bigger container to your production environment? Probably, no. That is why we need to build the production container in multiple stages.</p><pre><code>FROM rust:1.66.0-alpine3.17 AS build
WORKDIR /app/
COPY . .
RUN cargo build --release

FROM scratch
COPY --from=build /app/target/release/namaste-world /app/namaste-world
CMD ["/app/namaste-world"]
</code></pre><p>We use <code>rust:1.66.0-alpine3.17</code> to compile the application and then we copy the binary to another smaller (very small) container, called <code>scratch</code>.</p><pre><code>$ docker build . -t namaste-world:latest
[+] Building 0.1s (10/10) FINISHED                                                                                      
 =&gt; [internal] load build definition from Dockerfile                                                               0.0s
 =&gt; =&gt; transferring dockerfile: 74B                                                                                0.0s
 =&gt; [internal] load .dockerignore                                                                                  0.0s
 =&gt; =&gt; transferring context: 2B                                                                                    0.0s
 =&gt; [internal] load metadata for docker.io/library/rust:1.66.0-alpine3.17                                          0.0s
 =&gt; [internal] load build context                                                                                  0.0s
 =&gt; =&gt; transferring context: 7.29kB                                                                                0.0s
 =&gt; [build 1/4] FROM docker.io/library/rust:1.66.0-alpine3.17                                                      0.0s
 =&gt; CACHED [build 2/4] WORKDIR /app/                                                                               0.0s
 =&gt; CACHED [build 3/4] COPY . .                                                                                    0.0s
 =&gt; CACHED [build 4/4] RUN cargo build --release                                                                   0.0s
 =&gt; CACHED [stage-1 1/1] COPY --from=build /app/target/release/namaste-world /app/namaste-world                    0.0s
 =&gt; exporting to image                                                                                             0.0s
 =&gt; =&gt; exporting layers                                                                                            0.0s
 =&gt; =&gt; writing image sha256:44c98d7123b596ef4b90388ce73ee66391f5f38a04e75440dfb0a4399b436e94                       0.0s
 =&gt; =&gt; naming to docker.io/library/namaste-world:latest                                                            0.0s</code></pre><p>Once the container is built, let's run it.</p><pre><code>$ docker run --rm namaste-world
Namaste, world! 🙏
</code></pre><p>Now, let's have a look at the size of the container images.</p><pre><code>$ docker images
REPOSITORY      TAG                 IMAGE ID       CREATED        SIZE
namaste-world   latest              44c98d7123b5   2 hours ago    4.57MB
rust            1.66.0-alpine3.17   87eecbd0d066   38 hours ago   787MB</code></pre><p>See, the <code>scratch</code> container image holding the <code>namaste-world</code> binary is below <strong>5MB</strong> while the <code>rust:1.66.0-alpine3.17</code>  container image is <strong>787MB</strong>. When deploying to production it is best practice to use smaller images for less memory footprint.</p><hr><p><a href="https://twitter.com/renghenKornel">Renghen</a> and I talked after I published this post on Twitter &amp; LinkedIn. He shared his views about having a multi-stage build process. It makes more sense if it is part of a pipeline. He does not advise compiling applications using containers. He refers to an example where the compiler requires the GPU and such compilation won't be possible using a container. However, he stated that multi-stage builds makes sense in cases where certain languages have deprecated some features and one might still need those to run an application.</p>]]></content:encoded>
        </item>
        <item>
            <title>Laravel routes</title>
            <link>https://sysadmin-journal.com/laravel-routes</link>
            <guid isPermaLink="true">https://sysadmin-journal.com/laravel-routes</guid>
            <pubDate>Fri, 04 Nov 2022 16:50:05 +0000</pubDate>
            <dc:creator>Ish Sookun</dc:creator>
            <category>Laravel</category>
            <description>Laravel is an open source PHP framework created by Taylor Otwell. It is popular for creating web applications. Laravel has an elegant syntax and it very well documented. I started experimenting with Laravel since last year and it&#039;s been a great journey so far.</description>
            <content:encoded><![CDATA[<p>A route is the initial point of entry to your application. </p><p>Your application is accessible on the web via routes or call them URIs. They are defined in the <code>routes/web.php</code> file in your Laravel application. The routing feature is provided by a <a href="https://laravel.com/docs/9.x/facades">facade</a>.</p><pre><code class="language-php">use Illuminate\Support\Facades\Route;
</code></pre><p>In its simplest form, a route accepts a URI and a <a href="https://www.php.net/manual/en/functions.anonymous.php">closure</a> (i.e an anonymous function).</p><pre><code class="language-php">Route::get('/greeting', function () {
    return 'Namaste, world';
});

Route::get('/', function () {
    return view('greeting', ['name' =&gt; 'Angad']);
});

Route::get('/about', function () {
    return response()-&gt;json([
        'name'  =&gt; 'Angad',
        'level' =&gt; 'Warrior',
    ]);
});</code></pre><p>You can return a string, a <a href="https://laravel.com/docs/9.x/views">view</a> or other <a href="https://laravel.com/docs/9.x/responses">HTTP responses</a>.</p><p>You can register a URI to respond to a specific HTTP verb or respond to multiple HTTP verbs using the <code>match()</code> method.</p><pre><code class="language-php">Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
Route::options($uri, $callback);

Route::match(['get', 'post'], '/', function () {
    //
});</code></pre><p>If a URI should respond to any HTTP verb then you can do so using by using the <code>any()</code> method.</p><pre><code class="language-php">Route::any('/', function () {
    //
});</code></pre><h2 id="route-parameters">Route parameters</h2><p>Route parameters let you capture values from the URL. A parameter is specified by putting string within curly braces <code>{name}</code> in the URL. It can then be accessed by the controller.</p><pre><code class="language-php">Route::get('/blog/{id}', [PostController::class, 'show']);</code></pre><p>Then in the specified method in the controller you write the actions that are needed for this value. In the example above, this would be done in the <code>show</code> method of the <code>PostController</code> controller.</p><pre><code class="language-php">public function show($id) {
   // do something with $id
   return $id;
}</code></pre><p>This post is a work in progress. I will keep updating it with bits and pieces of useful information regarding Laravel routing for my own reference.</p>]]></content:encoded>
        </item>
        <item>
            <title>Modify content of password reset email in Laravel Jetstream</title>
            <link>https://sysadmin-journal.com/modify-content-of-password-reset-email-in-laravel-jetstream</link>
            <guid isPermaLink="true">https://sysadmin-journal.com/modify-content-of-password-reset-email-in-laravel-jetstream</guid>
            <pubDate>Tue, 08 Mar 2022 19:21:42 +0000</pubDate>
            <dc:creator>Ish Sookun</dc:creator>
            <category>Laravel</category>
            <description>Laravel Jetstream is an application starter kit beautifully designed using Tailwind CSS. It uses Fortify for authenticating users and has built-in features for user account registration, email verification, password resets etc.</description>
            <content:encoded><![CDATA[<p>During my recent experiments with Laravel Jetstream tried to change the content of the emails for the "email verification" and "password reset".</p><p>The below commands will generate some files which can be used to edit part of the email content.</p><pre><code>php artisan vendor:publish --tag=laravel-notifications
php artisan vendor:publish --tag=laravel-mail</code></pre><p>However, the reset of the layout for the emails are found in these two files:</p><pre><code>vendor/laravel/framework/src/Illuminate/Auth/Notifications/ResetPassword.php

vendor/laravel/framework/src/Illuminate/Auth/Notifications/VerifyEmail.php</code></pre><p>The above files being in the <code>vendor</code> directory are not tracked by <strong>git</strong> and they will be most likely overwritten when <strong>composer</strong> updates the packages. However, until I have found a better way to customise these emails, these files are what should be updated.</p>]]></content:encoded>
        </item>
        <item>
            <title>How to redirect to a URL with query parameters?</title>
            <link>https://sysadmin-journal.com/how-to-redirect-to-a-url-with-query-parameters</link>
            <guid isPermaLink="true">https://sysadmin-journal.com/how-to-redirect-to-a-url-with-query-parameters</guid>
            <pubDate>Mon, 28 Feb 2022 11:05:46 +0000</pubDate>
            <dc:creator>Ish Sookun</dc:creator>
            <category>Laravel</category>
            <description>Laravel helpers: the redirect() function returns a redirect HTTP response, or returns the redirector instance if called with no arguments:</description>
            <content:encoded><![CDATA[<p>While writing this method I needed it to return to the profile page of a user after successfully creating that user account. I don't know if I am doing it the correct way but one obvious way I thought is to return the browser a URL with the query parameter that uniquely identifies the user and pass in the new user's identity.</p><p>Then, in the voluminous documentation of <a href="https://laravel.com/docs/9.x/responses#redirects">Laravel 9</a>, I tried to find how to do it. So far, the best options are:</p><pre><code>$url = "https://example.com?key={$value}";

return redirect($link);</code></pre><p>Using a named route:</p><pre><code>return redirect()-&gt;route('route_name',['key'=&gt; $value]);</code></pre>]]></content:encoded>
        </item>
        <item>
            <title>Setup MailHog on openSUSE for development on Laravel</title>
            <link>https://sysadmin-journal.com/setup-mailhog-on-opensuse-for-development-on-laravel</link>
            <guid isPermaLink="true">https://sysadmin-journal.com/setup-mailhog-on-opensuse-for-development-on-laravel</guid>
            <pubDate>Sun, 27 Feb 2022 07:08:40 +0000</pubDate>
            <dc:creator>Ish Sookun</dc:creator>
            <category>Laravel</category>
            <description>MailHog is an email testing tool that can be very handy in web development and it&#039;s very easy to set up. I am using it in my local set up with Laravel 9.</description>
            <content:encoded><![CDATA[<p>MailHog is easy to set up and avoids developers the need to require a full-fledged SMTP server to test mail capabilities in their web application. Using MailHog with Laravel is straight forward as well.</p><p>To install MailHog on openSUSE you need to install Go.</p><pre><code>sudo zypper in go</code></pre><p>Then, get the Mailhog binary.</p><pre><code>go get github.com/mailhog/MailHog</code></pre><p>The Mailhog binary will be available in the <code>~/go/bin</code> directory. You can run it directly from there or add that to your <code>PATH</code> environment.</p><p>Once, you've executed the Mailhog binary, the application will be running on port 8025.</p><pre><code>ish@coffee-bar:~&gt; ~/go/bin/MailHog
2022/02/27 10:44:03 Using in-memory storage
2022/02/27 10:44:03 [SMTP] Binding to address: 0.0.0.0:1025
[HTTP] Binding to address: 0.0.0.0:8025
2022/02/27 10:44:03 Serving under http://0.0.0.0:8025/</code></pre><p>As you can see above, a SMTP service will be available on port 1025. It's part of MailHog and you need to do nothing to configure it.</p><p>To check the incoming emails you just have to head to the web application running on port 8025.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://sysadmin-journal.com/content/images/2022/02/mailhog-opensuse.png" class="kg-image" alt="MailHog running on openSUSE Tumbleweed" loading="lazy" width="1460" height="828" srcset="/content/images/size/w600/2022/02/mailhog-opensuse.png 600w, /content/images/size/w1000/2022/02/mailhog-opensuse.png 1000w, /content/images/2022/02/mailhog-opensuse.png 1460w" sizes="(min-width: 720px) 720px"><figcaption>MailHog running on openSUSE Tumbleweed</figcaption></figure><p>To enable your Laravel application to use MailHog, update the <code>.env</code> file with these parameters.</p><pre><code>MAIL_MAILER=smtp
MAIL_HOST=0.0.0.0
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=no-reply@example.com
MAIL_FROM_NAME="${APP_NAME}"</code></pre><p>All the emails sent using your Laravel app on your local machine will be available to be viewed on the MailHog web application.</p>]]></content:encoded>
        </item>
        <item>
            <title>Laravel Jetstream, redirect users after login</title>
            <link>https://sysadmin-journal.com/laravel-jetstream-redirect-users-after-login</link>
            <guid isPermaLink="true">https://sysadmin-journal.com/laravel-jetstream-redirect-users-after-login</guid>
            <pubDate>Mon, 14 Feb 2022 20:20:44 +0000</pubDate>
            <dc:creator>Ish Sookun</dc:creator>
            <category>Laravel</category>
            <description>Laravel Jetstream is an application starter kit beautifully designed using Tailwind CSS. It can be extended using two available front-end stacks, Laravel Livewire + Blade or Inertia + Vue. My preference is Laravel Livewire + Blade.</description>
            <content:encoded><![CDATA[<p>While experimenting with Laravel Jetstream recently I was looking at how to redirect users to a specific page after they log in. The authentication part is handled by Laravel Fortify, which is a feature-rich authentication back-end for Laravel.</p><p>I checked the documentation pages about authentication for <a href="https://jetstream.laravel.com/2.x/features/authentication.html">Laravel Jetstream</a> and <a href="https://laravel.com/docs/9.x/fortify#authentication">Fortify</a> but could not find any mention about changing the redirection path; unless I wasn't looking at the right place.</p><p>After some fiddling I understood that the <code>app/Providers/RouteServiceProvider.php</code> file has this <code>const</code> defined as <code>HOME</code> and it holds the path value for redirection after login.</p><pre><code>/**
* The path to the "home" route for your application.
*
* This is used by Laravel authentication to redirect users after login.
*
* @var string
*/
public const HOME = '/';</code></pre>]]></content:encoded>
        </item>
        <item>
            <title>Laravel, how to fetch records created within the month?</title>
            <link>https://sysadmin-journal.com/laravel-how-to-fetch-records-created-within-the-month</link>
            <guid isPermaLink="true">https://sysadmin-journal.com/laravel-how-to-fetch-records-created-within-the-month</guid>
            <pubDate>Tue, 11 Jan 2022 06:18:51 +0000</pubDate>
            <dc:creator>Ish Sookun</dc:creator>
            <category>Laravel</category>
            <category>PHP</category>
            <description>This post is about Laravel database queries and date format using Carbon, a PHP API extension for DateTime.</description>
            <content:encoded><![CDATA[<p>Today, I found this tip published by <a href="https://twitter.com/TheLaravelDev/status/1480500626840637441/photo/1">@TheLaravelDev </a>on Twitter. It's a handy piece of code that will allow you to fetch the records created between the start and the end of the month using <a href="https://carbon.nesbot.com/docs/">Carbon</a> in your Laravel project.</p><pre><code class="language-php">// Define scope within your model
public function scopeThisMonth(Builder $query): Builder
{
    $startDate = Carbon::now()-&gt;startOfMonth();
    $endDate = Carbon::now()-&gt;endOfMonth();
    return $query-&gt;whereBetween('created_at', [$startDate, $endDate]);
}

// Use the scope like below
Product::query()-&gt;thisMonth();</code></pre><h2 id="laravel-documentation">Laravel documentation</h2><p>The <code>whereBetween</code> method verifies that a column's value is between two values.</p><pre><code class="language-php">$users = DB::table('users')
           -&gt;whereBetween('votes', [1, 100])
           -&gt;get();</code></pre><p><a href="https://laravel.com/docs/8.x/queries#additional-where-clauses">Read more</a> on this.</p><p>For more interesting tips on <a href="https://laravel.com">Laravel</a> you can follow <a href="https://twitter.com/TheLaravelDev/status/1480500626840637441/photo/1">@TheLaravelDev</a>.</p>]]></content:encoded>
        </item>
    </channel>
</rss>
