<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Abdullo Akramov</title>
    <description>The latest articles on DEV Community by Abdullo Akramov (@abdullo_akramov).</description>
    <link>https://dev.to/abdullo_akramov</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2993820%2F1f57a534-5f57-4c9e-a0e4-7a36631a6d84.jpg</url>
      <title>DEV Community: Abdullo Akramov</title>
      <link>https://dev.to/abdullo_akramov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/abdullo_akramov"/>
    <language>en</language>
    <item>
      <title>From Web to Desktop with NativePHP: A PHP Developer’s Journey and Lessons Learned</title>
      <dc:creator>Abdullo Akramov</dc:creator>
      <pubDate>Sun, 06 Apr 2025 06:37:57 +0000</pubDate>
      <link>https://dev.to/abdullo_akramov/from-web-to-desktop-with-nativephp-a-php-developers-journey-and-lessons-learned-1330</link>
      <guid>https://dev.to/abdullo_akramov/from-web-to-desktop-with-nativephp-a-php-developers-journey-and-lessons-learned-1330</guid>
      <description>&lt;p&gt;Hey everyone! I’m a PHP and Laravel developer who’s spent years building web applications. Recently, I stumbled across NativePHP—a tool that promises to take PHP beyond the browser and into desktop apps. I was curious, so I decided to test it with my own project, a simple CRM system. The result? Honestly, it blew me away!&lt;/p&gt;

&lt;p&gt;In this article, I’ll share my experience in three parts: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Understanding what NativePHP is and how it works. &lt;/li&gt;
&lt;li&gt;Walking you through my hands-on project.&lt;/li&gt;
&lt;li&gt;Breaking down its strengths and weaknesses.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you’re a PHP developer wondering about desktop apps, stick with me—this might inspire you to try something new!&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Understanding NativePHP: A New World for PHP Developers
&lt;/h2&gt;

&lt;p&gt;Let’s start with the basics. NativePHP is a framework that lets you turn Laravel projects into native desktop applications. It’s built to work with tools like Electron (the same tech behind apps like VS Code) or Tauri, which are popular for creating cross-platform desktop apps.&lt;/p&gt;

&lt;p&gt;The big idea? You can write PHP code—something we usually run on servers—and make it work as a standalone app on someone’s computer. Here’s how it happens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NativePHP takes your Laravel project, adds a PHP runtime (so the app can understand PHP without a server), and combines it with a front-end made of HTML, CSS, and JavaScript.&lt;/li&gt;
&lt;li&gt;It then packages everything into a single file that users can download and run. No need for them to install PHP, Apache, or anything else—it’s all included.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For me, this was a game-changer. I’ve always thought of PHP as a web-only language, but NativePHP proves it can do more. The best part? If you know Laravel, you’re already halfway there. You can use Blade templates for the interface, Eloquent for data, and even Livewire if you want real-time updates.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Hands-On: Turning My Laravel CRM into a Desktop App
&lt;/h2&gt;

&lt;p&gt;Now, let’s get practical. I have a small Laravel project—a CRM system I built for managing clients. It worked fine as a web app, but one client asked, &lt;em&gt;“Can I use this without a browser?”&lt;/em&gt; That’s when I decided to try NativePHP.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Setting It Up
&lt;/h3&gt;

&lt;p&gt;I started fresh to keep things clean. First, I created a new Laravel project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer create-project laravel/laravel my-crm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, I added NativePHP with Electron as the engine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require nativephp/electron
php artisan native:install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This step installed the necessary tools, including some Node.js dependencies. It took about five minutes, and I was ready to test it. I ran:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan native:serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A window popped up on my screen—my CRM was now a desktop app! The client list loaded perfectly, and the “Add Client” button worked just like it did online. I couldn’t believe how fast it came together.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Customizing the App
&lt;/h3&gt;

&lt;p&gt;Next, I wanted to tweak it. In the &lt;code&gt;app/Providers/NativeAppServiceProvider.php&lt;/code&gt; file, I changed the window size and added a basic tray menu:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Native\Laravel\Facades\Window&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Native\Laravel\Facades\Menu&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;boot&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Window&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;width&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;900&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;height&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;700&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Quit'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;app&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;quit&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This made the app feel more polished. The window was bigger, and users could close it from the system tray.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Testing and Building
&lt;/h3&gt;

&lt;p&gt;I tested it on my Windows laptop and a friend’s Mac—it worked on both! To create a final version, I used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan native:build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gave me an executable file (&lt;code&gt;.exe&lt;/code&gt; for Windows, &lt;code&gt;.dmg&lt;/code&gt; for Mac). My client installed it like any other app—no server setup, no browser. They loved it because it felt faster and more professional than opening it in Chrome.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. The Pros and Cons: Is NativePHP Worth It?
&lt;/h2&gt;

&lt;p&gt;After playing with NativePHP, I’ve got a clear picture of its strengths and weaknesses.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Pros:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;✅ &lt;strong&gt;Super Easy for Laravel Fans&lt;/strong&gt; – If you know Laravel, you’ll feel at home. The setup is quick, and you don’t need to learn a new language or framework.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Fast Results&lt;/strong&gt; – Going from a web app to a desktop app takes almost no time. A few commands, some tweaks, and you’ve got something ready to share.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Cross-Platform Magic&lt;/strong&gt; – It works on Windows, macOS, and Linux with one codebase.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;PHP’s New Power&lt;/strong&gt; – Using PHP for desktop apps feels fresh. I can use my server-side skills in a new way.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;User-Friendly&lt;/strong&gt; – Clients don’t need technical knowledge to use it—just install and go.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Cons:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;❌ &lt;strong&gt;Still in Beta&lt;/strong&gt; – NativePHP isn’t fully polished yet. I hit a couple of bugs—like the build failing until I updated my Node.js version.&lt;/p&gt;

&lt;p&gt;❌ &lt;strong&gt;Big File Size&lt;/strong&gt; – Using Electron means the app can get heavy. My CRM ended up at 120 MB, which is a lot compared to a web app.&lt;/p&gt;

&lt;p&gt;❌ &lt;strong&gt;Database Limits&lt;/strong&gt; – Right now, it’s happiest with SQLite. If you rely on MySQL or PostgreSQL, you’ll need a workaround.&lt;/p&gt;

&lt;p&gt;❌ &lt;strong&gt;Not Super Fast&lt;/strong&gt; – While it’s quick to build, the app itself isn’t as snappy as something written in C++ or Rust.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;My Verdict:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;NativePHP isn’t perfect, but it’s a fantastic option for PHP developers who want to try desktop apps. It turned my CRM into something my client loves, and it didn’t take me out of my PHP comfort zone. It’s best for small-to-medium projects where speed and ease matter more than raw performance.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts: Why I’m Excited About NativePHP
&lt;/h2&gt;

&lt;p&gt;Trying NativePHP showed me that PHP doesn’t have to stay in the browser. As a Laravel developer, I’m used to solving problems for the web, but now I can offer desktop solutions too—all with the tools I already know.&lt;/p&gt;

&lt;p&gt;My little CRM experiment proved it’s practical and fun. Sure, there are rough edges, but for a tool this new, it’s impressive. &lt;/p&gt;

&lt;p&gt;If you’re a PHP developer, I recommend giving NativePHP a shot. Start with a small project, play around, and see where it takes you.&lt;/p&gt;

&lt;p&gt;Have you tried it yet? Or do you have questions about my experience? Let’s chat in the comments—I’d love to hear your thoughts!&lt;/p&gt;

</description>
      <category>php</category>
      <category>laravel</category>
      <category>nativephp</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>🚀 Protect Your Laravel API: How I Mastered Rate Limiting in a Real Project</title>
      <dc:creator>Abdullo Akramov</dc:creator>
      <pubDate>Sun, 30 Mar 2025 13:01:02 +0000</pubDate>
      <link>https://dev.to/abdullo_akramov/protect-your-laravel-api-how-i-mastered-rate-limiting-in-a-real-project-48dk</link>
      <guid>https://dev.to/abdullo_akramov/protect-your-laravel-api-how-i-mastered-rate-limiting-in-a-real-project-48dk</guid>
      <description>&lt;p&gt;Hey DEV community! 👋 Ever had that moment when you realize your API could get overwhelmed by too many requests? I faced that exact issue in a recent Laravel project and decided to tackle it with &lt;strong&gt;Rate Limiting&lt;/strong&gt;. Spoiler: It worked like a charm! In this post, I’ll break down what Rate Limiting is and show you how I applied it to my project with some handy code snippets. Let’s dive in! 🔒&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is Rate Limiting? (The Quick Version)
&lt;/h2&gt;

&lt;p&gt;Rate Limiting is like putting a bouncer at your API’s door: &lt;strong&gt;“Only 10 requests per minute — everyone else waits!”&lt;/strong&gt; I needed this in my project to keep things running smoothly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why It’s a Game-Changer 🚀
&lt;/h2&gt;

&lt;p&gt;Here’s why I decided to use it:&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Security&lt;/strong&gt;: Stops bots from spamming my API (think brute-force attacks).&lt;br&gt;
✅ &lt;strong&gt;Server Health&lt;/strong&gt;: Keeps my server from choking on too many requests.&lt;br&gt;
✅ &lt;strong&gt;Fairness&lt;/strong&gt;: Ensures all users get a smooth experience, no matter the traffic.&lt;/p&gt;


&lt;h2&gt;
  
  
  Laravel’s Rate Limiting Superpowers 🦸‍♂️
&lt;/h2&gt;

&lt;p&gt;Laravel makes Rate Limiting a breeze with some awesome tools. I experimented with &lt;strong&gt;two approaches&lt;/strong&gt; in my project.&lt;/p&gt;
&lt;h3&gt;
  
  
  Approach 1: The Manual Way with &lt;code&gt;RateLimiter&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Laravel’s &lt;code&gt;RateLimiter&lt;/code&gt; facade lets you control limits manually. Here’s what I used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;hit&lt;/code&gt;: Tracks each request. Example: &lt;code&gt;RateLimiter::hit('api', 60)&lt;/code&gt; logs a request for the &lt;code&gt;api&lt;/code&gt; key, resetting after &lt;strong&gt;60 seconds&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tooManyAttempts&lt;/code&gt;: Checks if the limit’s exceeded. &lt;code&gt;RateLimiter::tooManyAttempts('api', 10)&lt;/code&gt; returns &lt;code&gt;true&lt;/code&gt; if there’s more than &lt;strong&gt;10 requests&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Implementation:
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'contacts:'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nc"&gt;RateLimiter&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;hit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RateLimiter&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;tooManyAttempts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$seconds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RateLimiter&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;availableIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Whoa! Too many requests. Wait &lt;/span&gt;&lt;span class="nv"&gt;$seconds&lt;/span&gt;&lt;span class="s2"&gt; seconds!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;429&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This worked, but I found myself &lt;strong&gt;repeating this code everywhere&lt;/strong&gt; — not ideal. 😅&lt;/p&gt;


&lt;h3&gt;
  
  
  Approach 2: The Magic of &lt;code&gt;throttle&lt;/code&gt; Middleware ✨
&lt;/h3&gt;

&lt;p&gt;Then I discovered Laravel’s &lt;strong&gt;&lt;code&gt;throttle&lt;/code&gt; middleware&lt;/strong&gt;, and it was a game-changer! I set up a named limit using &lt;code&gt;RateLimiter::for&lt;/code&gt; in &lt;strong&gt;RouteServiceProvider&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Cache\RateLimiting\Limit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\RateLimiter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;configureRateLimiting&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;RateLimiter&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'contacts'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;user&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nc"&gt;Limit&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;perMinute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 20 for logged-in users&lt;/span&gt;
            &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Limit&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;perMinute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// 10 for others&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I applied it to my routes in &lt;strong&gt;routes/api.php&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'contacts'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'throttle:contacts'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;ContactController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'index'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;ContactController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'store'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach &lt;strong&gt;kept my controller clean&lt;/strong&gt; — no manual checks needed! 😍&lt;/p&gt;




&lt;h2&gt;
  
  
  My Project: A Contacts API with Rate Limiting 🛡️
&lt;/h2&gt;

&lt;p&gt;For my project, I built a simple API to manage contacts (&lt;strong&gt;viewing and adding contacts&lt;/strong&gt;). I wanted to make sure it could handle traffic without breaking, so I added &lt;strong&gt;Rate Limiting&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Controller
&lt;/h3&gt;

&lt;p&gt;Here’s the controller I used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Http\Controllers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Models\Contact&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Http\Request&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ContactController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Controller&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Contact&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$validated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'required|string|max:255'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'phone'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'required|string|max:20'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="nv"&gt;$contact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Contact&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$validated&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$contact&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks to &lt;strong&gt;throttle middleware&lt;/strong&gt;, I didn’t need to add any &lt;strong&gt;Rate Limiting logic&lt;/strong&gt; here. If users hit the limit, Laravel &lt;strong&gt;automatically&lt;/strong&gt; returns a &lt;strong&gt;“429” Too Many Requests&lt;/strong&gt; response. 🎯&lt;/p&gt;




&lt;h2&gt;
  
  
  Testing It Out 🔍
&lt;/h2&gt;

&lt;p&gt;I tested it with &lt;strong&gt;Postman&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unauthenticated&lt;/strong&gt;: 10 &lt;code&gt;GET&lt;/code&gt; requests worked fine; the 11th got a &lt;strong&gt;“429” error&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;With a token (Sanctum)&lt;/strong&gt;: I hit 20 requests smoothly, but the 21st triggered the limit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It was amazing to see how &lt;strong&gt;little code&lt;/strong&gt; I needed to keep my API safe! 🛡️&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways 📌
&lt;/h2&gt;

&lt;p&gt;Using &lt;strong&gt;Rate Limiting&lt;/strong&gt; in my Laravel project was a total &lt;strong&gt;win&lt;/strong&gt;. It’s now a &lt;strong&gt;go-to tool&lt;/strong&gt; for me whenever I build APIs. Here’s what I learned:&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Use &lt;code&gt;RateLimiter&lt;/code&gt; for fine-grained control, but &lt;code&gt;throttle&lt;/code&gt; for simplicity.&lt;/strong&gt;&lt;br&gt;
✅ &lt;strong&gt;Protect your server and keep your users happy with just a few lines of code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Have you tried Rate Limiting in your projects?&lt;/strong&gt; Drop a comment — I’d love to hear your thoughts! If you want to dive deeper, check out my &lt;strong&gt;full setup on Medium&lt;/strong&gt;. 🚀&lt;/p&gt;




&lt;h3&gt;
  
  
  📢 Tags:
&lt;/h3&gt;

&lt;h1&gt;
  
  
  Laravel #RateLimiting #PHP #WebDevelopment #API
&lt;/h1&gt;

</description>
      <category>laravel</category>
      <category>ratelimiting</category>
      <category>php</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
