<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Afaz's Blog]]></title><description><![CDATA[Full-stack web developer. I work with Laravel, Nodejs, Vuejs, React, TailwindCSS and Bootstrap technologies.]]></description><link>https://afazkhatri.com</link><generator>RSS for Node</generator><lastBuildDate>Thu, 16 Apr 2026 01:45:43 GMT</lastBuildDate><atom:link href="https://afazkhatri.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Laravel Zap: Supercharging Your Schedule Management in Laravel]]></title><description><![CDATA[In the dynamic world of web development, efficiency and robust functionality are paramount. For Laravel developers, managing complex schedules, appointments, and time-based events has often presented a challenge, requiring significant custom developm...]]></description><link>https://afazkhatri.com/laravel-zap-schedule-management</link><guid isPermaLink="true">https://afazkhatri.com/laravel-zap-schedule-management</guid><category><![CDATA[Laravel]]></category><category><![CDATA[scheduling]]></category><dc:creator><![CDATA[Afaz Khatri]]></dc:creator><pubDate>Sat, 28 Jun 2025 11:00:56 GMT</pubDate><content:encoded><![CDATA[<p>In the dynamic world of web development, efficiency and robust functionality are paramount. For Laravel developers, managing complex schedules, appointments, and time-based events has often presented a challenge, requiring significant custom development. Enter <strong>Laravel Zap</strong>, a powerful and flexible package designed to revolutionize how you handle temporal operations within your Laravel applications.</p>
<p>Laravel Zap isn't just another library; it's a comprehensive schedule management system that deeply integrates with Laravel's ecosystem, making scheduling feel like a native, effortless part of your development workflow.</p>
<h3 id="heading-what-is-laravel-zap">What is Laravel Zap?</h3>
<p>At its core, Laravel Zap provides a fluent and intuitive API for creating, managing, and querying schedules. Whether you're building a doctor's appointment booking system, a meeting room management solution, or an employee shift scheduler, Zap offers the tools you need to handle intricate temporal logic with ease.</p>
<p><strong>Key Features that Make Laravel Zap Stand Out:</strong></p>
<ul>
<li><p><strong>Eloquent Integration:</strong> Zap seamlessly integrates with Laravel's Eloquent ORM. By simply adding the <code>HasSchedules</code> trait to any of your models (e.g., <code>User</code>, <code>Doctor</code>, <code>Room</code>), you can instantly equip them with schedule management capabilities, complete with full relationship support.</p>
<p>  <strong>Example: Adding the</strong> <code>HasSchedules</code> trait to a <code>Doctor</code> model</p>
<pre><code class="lang-php">  <span class="hljs-meta">&lt;?php</span>

  <span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">Models</span>;

  <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Database</span>\<span class="hljs-title">Eloquent</span>\<span class="hljs-title">Model</span>;
  <span class="hljs-keyword">use</span> <span class="hljs-title">Zap</span>\<span class="hljs-title">Traits</span>\<span class="hljs-title">HasSchedules</span>; <span class="hljs-comment">// Assuming Zap is in the Zap namespace</span>

  <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Doctor</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Model</span>
  </span>{
      <span class="hljs-keyword">use</span> <span class="hljs-title">HasSchedules</span>;

      <span class="hljs-keyword">protected</span> $fillable = [<span class="hljs-string">'name'</span>, <span class="hljs-string">'specialty'</span>];

      <span class="hljs-comment">// ... other model properties and methods</span>
  }
</code></pre>
</li>
<li><p><strong>Smart Conflict Detection:</strong> Say goodbye to double-bookings and overlapping schedules. Zap boasts an intelligent conflict detection system that automatically prevents such occurrences. You can even customize buffer times and enable strict mode validation for precise control.</p>
<p>  <strong>Example: Checking for conflicts before creating a new appointment</strong></p>
<pre><code class="lang-php">  <span class="hljs-meta">&lt;?php</span>

  <span class="hljs-keyword">use</span> <span class="hljs-title">Carbon</span>\<span class="hljs-title">Carbon</span>;

  $doctor = Doctor::find(<span class="hljs-number">1</span>);
  $startTime = Carbon::parse(<span class="hljs-string">'2025-07-01 09:00:00'</span>);
  $endTime = Carbon::parse(<span class="hljs-string">'2025-07-01 09:30:00'</span>);

  <span class="hljs-keyword">if</span> ($doctor-&gt;schedules()-&gt;isConflicting($startTime, $endTime)) {
      <span class="hljs-keyword">echo</span> <span class="hljs-string">"Doctor is not available at this time. Conflict detected!"</span>;
  } <span class="hljs-keyword">else</span> {
      $doctor-&gt;schedules()-&gt;create([
          <span class="hljs-string">'start_time'</span> =&gt; $startTime,
          <span class="hljs-string">'end_time'</span> =&gt; $endTime,
          <span class="hljs-string">'type'</span> =&gt; <span class="hljs-string">'appointment'</span>, <span class="hljs-comment">// Custom schedule type</span>
          <span class="hljs-string">'notes'</span> =&gt; <span class="hljs-string">'Patient John Doe'</span>
      ]);
      <span class="hljs-keyword">echo</span> <span class="hljs-string">"Appointment successfully booked!"</span>;
  }
</code></pre>
<p>  <strong>Flexible Recurring Patterns:</strong> From daily stand-ups to monthly maintenance windows, Zap handles recurring schedules with remarkable flexibility. Define daily, weekly, monthly, or even custom patterns to accommodate any business-specific scheduling scenario.</p>
<p>  <strong>Example: Creating a weekly recurring meeting</strong></p>
<pre><code class="lang-php">  <span class="hljs-meta">&lt;?php</span>

  <span class="hljs-keyword">use</span> <span class="hljs-title">Carbon</span>\<span class="hljs-title">Carbon</span>;

  $room = Room::find(<span class="hljs-number">5</span>);
  $room-&gt;schedules()-&gt;create([
      <span class="hljs-string">'start_time'</span> =&gt; Carbon::parse(<span class="hljs-string">'2025-07-02 10:00:00'</span>), <span class="hljs-comment">// First occurrence</span>
      <span class="hljs-string">'end_time'</span> =&gt; Carbon::parse(<span class="hljs-string">'2025-07-02 11:00:00'</span>),
      <span class="hljs-string">'type'</span> =&gt; <span class="hljs-string">'team_meeting'</span>,
      <span class="hljs-string">'recurrence'</span> =&gt; <span class="hljs-string">'weekly'</span>, <span class="hljs-comment">// 'daily', 'monthly', 'yearly', or custom cron string</span>
      <span class="hljs-string">'ends_on'</span> =&gt; Carbon::parse(<span class="hljs-string">'2025-12-31 23:59:59'</span>), <span class="hljs-comment">// Optional end date</span>
      <span class="hljs-string">'notes'</span> =&gt; <span class="hljs-string">'Weekly sync-up'</span>
  ]);
</code></pre>
</li>
<li><p><strong>Carbon-Powered Temporal Operations:</strong> Built on top of Laravel's robust Carbon library, Zap provides comprehensive date and time manipulation, including full timezone support. This is crucial for applications serving a global user base.</p>
<p>  <strong>Example: Fetching schedules in a specific timezone</strong></p>
<pre><code class="lang-php">  <span class="hljs-meta">&lt;?php</span>

  <span class="hljs-keyword">use</span> <span class="hljs-title">Carbon</span>\<span class="hljs-title">Carbon</span>;

  $user = User::find(<span class="hljs-number">10</span>);
  $userSchedules = $user-&gt;schedules()
                        -&gt;forDate(Carbon::today(<span class="hljs-string">'America/New_York'</span>))
                        -&gt;get();

  <span class="hljs-keyword">foreach</span> ($userSchedules <span class="hljs-keyword">as</span> $schedule) {
      <span class="hljs-keyword">echo</span> <span class="hljs-string">"Schedule from "</span> . $schedule-&gt;start_time-&gt;setTimezone(<span class="hljs-string">'Europe/London'</span>)-&gt;format(<span class="hljs-string">'Y-m-d H:i:s'</span>) . <span class="hljs-string">"\n"</span>;
  }
</code></pre>
</li>
<li><p><strong>Availability Management:</strong> One of Zap's most powerful features is its availability system. Easily check if a resource is available at a specific time or retrieve all available time slots for a given day, making appointment booking a breeze.</p>
<p>  <strong>Example: Getting available slots for a doctor</strong></p>
<pre><code class="lang-php">  <span class="hljs-meta">&lt;?php</span>

  <span class="hljs-keyword">use</span> <span class="hljs-title">Carbon</span>\<span class="hljs-title">Carbon</span>;

  $doctor = Doctor::find(<span class="hljs-number">1</span>);
  $date = Carbon::parse(<span class="hljs-string">'2025-07-05'</span>);
  $slotDuration = <span class="hljs-number">30</span>; <span class="hljs-comment">// minutes</span>

  $availableSlots = $doctor-&gt;schedules()-&gt;getAvailableSlots($date, $slotDuration, [
      <span class="hljs-string">'start_of_day'</span> =&gt; <span class="hljs-string">'09:00'</span>, <span class="hljs-comment">// Doctor's working hours</span>
      <span class="hljs-string">'end_of_day'</span> =&gt; <span class="hljs-string">'17:00'</span>,
      <span class="hljs-string">'break_times'</span> =&gt; [
          [<span class="hljs-string">'start'</span> =&gt; <span class="hljs-string">'13:00'</span>, <span class="hljs-string">'end'</span> =&gt; <span class="hljs-string">'14:00'</span>] <span class="hljs-comment">// Lunch break</span>
      ]
  ]);

  <span class="hljs-keyword">echo</span> <span class="hljs-string">"Available slots for Doctor on "</span> . $date-&gt;toDateString() . <span class="hljs-string">":\n"</span>;
  <span class="hljs-keyword">foreach</span> ($availableSlots <span class="hljs-keyword">as</span> $slot) {
      <span class="hljs-keyword">echo</span> $slot[<span class="hljs-string">'start'</span>]-&gt;format(<span class="hljs-string">'H:i'</span>) . <span class="hljs-string">" - "</span> . $slot[<span class="hljs-string">'end'</span>]-&gt;format(<span class="hljs-string">'H:i'</span>) . <span class="hljs-string">"\n"</span>;
  }
</code></pre>
</li>
<li><p><strong>Performance Optimization:</strong> Zap is engineered for performance. It includes caching support for frequently accessed schedule data, eager loading capabilities to prevent N+1 queries, and recommendations for database indexing to ensure optimal speed.</p>
<p>  <strong>Example: Eager loading schedules with a model</strong></p>
<pre><code class="lang-php">  <span class="hljs-meta">&lt;?php</span>

  $doctors = Doctor::with(<span class="hljs-string">'schedules'</span>)-&gt;get();

  <span class="hljs-keyword">foreach</span> ($doctors <span class="hljs-keyword">as</span> $doctor) {
      <span class="hljs-keyword">echo</span> $doctor-&gt;name . <span class="hljs-string">" has "</span> . $doctor-&gt;schedules-&gt;count() . <span class="hljs-string">" schedules.\n"</span>;
  }
</code></pre>
</li>
<li><p><strong>Developer Experience (DX):</strong> With a fluent API, clear documentation, and comprehensive testing, Laravel Zap prioritizes the developer experience, making it a joy to work with.</p>
</li>
</ul>
<h3 id="heading-use-cases-for-laravel-zap">Use Cases for Laravel Zap</h3>
<p>The versatility of Laravel Zap makes it suitable for a wide array of applications:</p>
<ul>
<li><p><strong>Appointment Booking Systems:</strong> For clinics, salons, consultants, or any service provider requiring client appointments.</p>
</li>
<li><p><strong>Meeting Room Management:</strong> Efficiently manage shared resources like meeting rooms, ensuring no conflicts.</p>
</li>
<li><p><strong>Employee Shift Management:</strong> Create and manage complex employee work schedules, including recurring shifts and overtime.</p>
</li>
<li><p><strong>Event Management Platforms:</strong> Organize and track events, workshops, or classes with specific start and end times.</p>
</li>
<li><p><strong>Resource Allocation:</strong> Manage the availability of equipment, vehicles, or any other bookable resource.</p>
</li>
</ul>
<h3 id="heading-why-choose-laravel-zap">Why Choose Laravel Zap?</h3>
<p>Choosing Laravel Zap means choosing:</p>
<ul>
<li><p><strong>Laravel-Native Solution:</strong> It feels like a natural extension of your Laravel application.</p>
</li>
<li><p><strong>Enhanced Developer Productivity:</strong> Its intuitive API and powerful features save significant development time.</p>
</li>
<li><p><strong>Reliability and Accuracy:</strong> Robust conflict detection ensures accurate and reliable scheduling.</p>
</li>
<li><p><strong>Scalability:</strong> Designed to handle both small-scale appointment systems and complex enterprise-level scheduling platforms.</p>
</li>
<li><p><strong>Active Community and Maintenance:</strong> Benefit from ongoing development and community support.</p>
</li>
</ul>
<p>Laravel Zap is an open-source package licensed under the MIT License, ready to empower your next Laravel project.</p>
]]></content:encoded></item><item><title><![CDATA[Vue 3's provide and inject: Master Data Flow in Complex Apps]]></title><description><![CDATA[Welcome to the world of Vue 3! As you build more complex applications, you'll inevitably encounter scenarios where passing data down through many layers of components becomes cumbersome. This is often called "prop drilling," and it can make your code...]]></description><link>https://afazkhatri.com/vue-3s-provide-and-inject-master-data-flow-in-complex-apps</link><guid isPermaLink="true">https://afazkhatri.com/vue-3s-provide-and-inject-master-data-flow-in-complex-apps</guid><category><![CDATA[Vue.js]]></category><dc:creator><![CDATA[Afaz Khatri]]></dc:creator><pubDate>Fri, 06 Jun 2025 04:30:08 GMT</pubDate><content:encoded><![CDATA[<p>Welcome to the world of Vue 3! As you build more complex applications, you'll inevitably encounter scenarios where passing data down through many layers of components becomes cumbersome. This is often called "prop drilling," and it can make your code harder to read, maintain, and debug.</p>
<p>Vue 3 offers an elegant solution: the <code>provide</code> and <code>inject</code> API. While seemingly simple, mastering its nuances, especially around reactivity and edge cases, is crucial for building robust and scalable applications. Let's explore!</p>
<h2 id="heading-what-are-provide-and-inject"><strong>What are</strong> <code>provide</code> and <code>inject</code>?</h2>
<p>At their core, <code>provide</code> and <code>inject</code> allow an ancestor component (a "provider") to make data available to any of its descendant components (an "injector"), regardless of how deeply nested they are. Think of it as a localized "dependency injection" system for your component tree.</p>
<p>This differs from props, which only allow data flow from parent to <em>direct</em> child. With <code>provide</code> and <code>inject</code>, intermediate components don't need to know about the data being passed, leading to cleaner code.</p>
<h3 id="heading-basic-usage"><strong>Basic Usage</strong></h3>
<p><strong>1. Providing Data (Ancestor Component)</strong></p>
<p>In a parent component, you use the <code>provide</code> function. It takes two arguments:</p>
<ul>
<li><p>A <code>key</code>: A unique identifier (preferably a <code>Symbol</code> for type safety and to avoid collision).</p>
</li>
<li><p>A <code>value</code>: The data you want to make available.</p>
</li>
</ul>
<pre><code class="lang-javascript">&lt;script setup&gt;
<span class="hljs-keyword">import</span> { provide, ref } <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span>;

<span class="hljs-comment">// Define a Symbol for the key to prevent naming conflicts</span>
<span class="hljs-keyword">const</span> AppConfigKey = <span class="hljs-built_in">Symbol</span>(<span class="hljs-string">'appConfig'</span>); 

<span class="hljs-keyword">const</span> appSettings = ref({
  <span class="hljs-attr">theme</span>: <span class="hljs-string">'dark'</span>,
  <span class="hljs-attr">language</span>: <span class="hljs-string">'en'</span>
});

provide(AppConfigKey, appSettings); 
&lt;/script&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Application Settings<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">DeeplyNestedComponent</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span></span>
</code></pre>
<p>Here, <code>appSettings</code> (a reactive <code>ref</code>) is provided under the <code>AppConfigKey</code>.</p>
<p><strong>2. Injecting Data (Descendant Component)</strong></p>
<p>In any descendant component, you use the <code>inject</code> function with the <em>same key</em> to retrieve the provided value.</p>
<pre><code class="lang-javascript">&lt;script setup&gt;
<span class="hljs-keyword">import</span> { inject } <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span>;

<span class="hljs-keyword">const</span> AppConfigKey = <span class="hljs-built_in">Symbol</span>(<span class="hljs-string">'appConfig'</span>); <span class="hljs-comment">// Must be the same Symbol as provided</span>

<span class="hljs-comment">// Inject the provided value. The second argument is an optional default.</span>
<span class="hljs-keyword">const</span> config = inject(AppConfigKey, { <span class="hljs-attr">theme</span>: <span class="hljs-string">'light'</span>, <span class="hljs-attr">language</span>: <span class="hljs-string">'es'</span> }); 

<span class="hljs-comment">// `config` is a Ref, so access its value with .value</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Current theme:'</span>, config.value.theme); 
&lt;/script&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>The current theme is: {{ config.theme }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span></span>
</code></pre>
<p>If <code>AppConfigKey</code> wasn't provided by an ancestor, <code>config</code> would default to <code>{ theme: 'light', language: 'es' }</code>.</p>
<h2 id="heading-reactivity-in-provide-and-inject"><strong>Reactivity in</strong> <code>provide</code> and <code>inject</code></h2>
<p>This is where it gets powerful! When you <code>provide</code> a <strong>reactive</strong> value (like a <code>ref</code> or <code>reactive</code> object), the injected value in descendant components will <em>also be reactive</em>. This means any changes to the original provided value will automatically propagate down the component tree.</p>
<pre><code class="lang-javascript">&lt;script setup&gt;
<span class="hljs-keyword">import</span> { provide, ref } <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span>;
<span class="hljs-keyword">const</span> SharedCounterKey = <span class="hljs-built_in">Symbol</span>(<span class="hljs-string">'sharedCounter'</span>);
<span class="hljs-keyword">const</span> counter = ref(<span class="hljs-number">0</span>); <span class="hljs-comment">// Reactive ref</span>

provide(SharedCounterKey, counter);

<span class="hljs-comment">// Function to increment the counter</span>
<span class="hljs-keyword">const</span> increment = <span class="hljs-function">() =&gt;</span> {
  counter.value++;
};
&lt;/script&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Parent Counter: {{ counter }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"increment"</span>&gt;</span>Increment from Parent<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ChildComponent</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">setup</span>&gt;</span><span class="javascript">
<span class="hljs-keyword">import</span> { inject } <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span>;
<span class="hljs-keyword">const</span> SharedCounterKey = <span class="hljs-built_in">Symbol</span>(<span class="hljs-string">'sharedCounter'</span>);
<span class="hljs-keyword">const</span> counter = inject(SharedCounterKey); <span class="hljs-comment">// Injected as a reactive ref</span>

<span class="hljs-comment">// A computed property reacting to the injected ref</span>
<span class="hljs-keyword">import</span> { computed } <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span>;
<span class="hljs-keyword">const</span> doubleCounter = computed(<span class="hljs-function">() =&gt;</span> counter.value * <span class="hljs-number">2</span>);

<span class="hljs-comment">// Function to decrement the counter (mutates the provided ref)</span>
<span class="hljs-keyword">const</span> decrement = <span class="hljs-function">() =&gt;</span> {
  counter.value--;
};
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Child Counter: {{ counter }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Double Counter: {{ doubleCounter }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"decrement"</span>&gt;</span>Decrement from Child<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span></span>
</code></pre>
<p>In this example, changing <code>counter</code> in <code>ParentComponent</code> or <code>ChildComponent</code> will update both.</p>
<p><strong>Important:</strong> If you provide a plain (non-reactive) value, it will <em>not</em> be reactive in the injecting components. Changes to the original value won't trigger updates.</p>
<h2 id="heading-edge-cases-and-best-practices"><strong>Edge Cases and Best Practices</strong></h2>
<h3 id="heading-1-modifying-provided-state"><strong>1. Modifying Provided State</strong></h3>
<p>While you <em>can</em> mutate an injected <code>ref</code> (as shown with <code>decrement</code> above), it's generally a <strong>best practice</strong> to keep state mutations co-located with the <code>provider</code>. This makes your data flow easier to trace and debug.</p>
<p>Instead of directly modifying <code>counter.value</code> in the child, the parent could provide a mutation function:</p>
<pre><code class="lang-javascript">&lt;script setup&gt;
<span class="hljs-keyword">import</span> { provide, ref } <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span>;
<span class="hljs-keyword">const</span> SharedCounterKey = <span class="hljs-built_in">Symbol</span>(<span class="hljs-string">'sharedCounter'</span>);
<span class="hljs-keyword">const</span> counter = ref(<span class="hljs-number">0</span>);

<span class="hljs-comment">// Provide both the reactive state and a function to modify it</span>
provide(SharedCounterKey, {
  <span class="hljs-attr">count</span>: counter,
  <span class="hljs-attr">increment</span>: <span class="hljs-function">() =&gt;</span> counter.value++,
  decrement: <span class="hljs-function">() =&gt;</span> counter.value--
});
&lt;/script&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">setup</span>&gt;</span><span class="javascript">
<span class="hljs-keyword">import</span> { inject } <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span>;
<span class="hljs-keyword">const</span> SharedCounterKey = <span class="hljs-built_in">Symbol</span>(<span class="hljs-string">'sharedCounter'</span>);
<span class="hljs-keyword">const</span> { count, increment, decrement } = inject(SharedCounterKey); 
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Child Counter: {{ count }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"increment"</span>&gt;</span>Increment from Child<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"decrement"</span>&gt;</span>Decrement from Child<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span></span>
</code></pre>
<p>This pattern is cleaner as the parent remains the sole owner of the <code>counter</code>'s modification logic.</p>
<h3 id="heading-2-collisions-with-string-keys"><strong>2. Collisions with String Keys</strong></h3>
<p>Using simple strings as keys (e.g., <code>provide('myKey', value)</code>) can lead to unexpected behavior if multiple ancestor components <em>accidentally</em> use the same string key. The <code>inject</code> call will always resolve to the value provided by the <em>closest</em> ancestor in the component chain.</p>
<p><strong>Solution:</strong> Use <code>Symbol</code>s for injection keys. Create a separate file (e.g., <code>src/keys.js</code>) to export unique symbols:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// src/keys.js</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> AppConfigKey = <span class="hljs-built_in">Symbol</span>(<span class="hljs-string">'appConfig'</span>);
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> ThemeKey = <span class="hljs-built_in">Symbol</span>(<span class="hljs-string">'theme'</span>);
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> LoggerKey = <span class="hljs-built_in">Symbol</span>(<span class="hljs-string">'loggerService'</span>);
</code></pre>
<p>Then, import and use them:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ProviderComponent.vue</span>
&lt;script setup&gt;
<span class="hljs-keyword">import</span> { provide, ref } <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span>;
<span class="hljs-keyword">import</span> { ThemeKey } <span class="hljs-keyword">from</span> <span class="hljs-string">'@/keys'</span>;

<span class="hljs-keyword">const</span> theme = ref(<span class="hljs-string">'dark'</span>);
provide(ThemeKey, theme);
&lt;/script&gt;

<span class="hljs-comment">// ConsumerComponent.vue</span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">setup</span>&gt;</span><span class="javascript">
<span class="hljs-keyword">import</span> { inject } <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span>;
<span class="hljs-keyword">import</span> { ThemeKey } <span class="hljs-keyword">from</span> <span class="hljs-string">'@/keys'</span>;

<span class="hljs-keyword">const</span> theme = inject(ThemeKey);
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>
</code></pre>
<p>This guarantees uniqueness and better type inference with TypeScript.</p>
<h3 id="heading-3-default-values-with-inject"><strong>3. Default Values with</strong> <code>inject</code></h3>
<p>The <code>inject</code> function can take a second argument: a default value. This is highly recommended for robustness, as it prevents errors if a component tries to inject something that hasn't been provided by an ancestor.</p>
<pre><code class="lang-javascript">&lt;script setup&gt;
<span class="hljs-keyword">import</span> { inject } <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span>;
<span class="hljs-keyword">import</span> { AppConfigKey } <span class="hljs-keyword">from</span> <span class="hljs-string">'@/keys'</span>;

<span class="hljs-comment">// If AppConfigKey is not provided, this will use the default object</span>
<span class="hljs-keyword">const</span> config = inject(AppConfigKey, {
  <span class="hljs-attr">theme</span>: <span class="hljs-string">'default-theme'</span>,
  <span class="hljs-attr">language</span>: <span class="hljs-string">'en-US'</span>
});
&lt;/script&gt;
</code></pre>
<p>For expensive default values (e.g., creating a large object or calling an API), you can provide a <strong>factory function</strong> as the default, coupled with <code>true</code> as the third argument. This ensures the default value is only created if truly needed.</p>
<pre><code class="lang-javascript">&lt;script setup&gt;
<span class="hljs-keyword">import</span> { inject } <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span>;
<span class="hljs-keyword">import</span> { AppConfigKey } <span class="hljs-keyword">from</span> <span class="hljs-string">'@/keys'</span>;

<span class="hljs-keyword">const</span> config = inject(AppConfigKey, <span class="hljs-function">() =&gt;</span> ({
  <span class="hljs-attr">theme</span>: <span class="hljs-string">'fallback-theme'</span>,
  <span class="hljs-attr">language</span>: <span class="hljs-string">'default'</span>
}), <span class="hljs-literal">true</span>); <span class="hljs-comment">// `true` indicates the second argument is a factory</span>
&lt;/script&gt;
</code></pre>
<h3 id="heading-4-when-to-use-provideinject-vs-other-solutions"><strong>4. When to Use</strong> <code>provide</code>/<code>inject</code> vs. Other Solutions</h3>
<ul>
<li><p><strong>Props:</strong> Use for direct parent-to-child communication where data flows one level down. Prefer props when possible due to explicit data flow.</p>
</li>
<li><p><strong>Emits:</strong> Use for child-to-parent communication (child "emits" an event, parent "listens").</p>
</li>
<li><p><strong>Vuex/Pinia (State Management Libraries):</strong> Use for truly global application state that needs to be accessed and modified from <em>anywhere</em> in your app, often with complex state logic, mutations, and actions. <code>provide</code>/<code>inject</code> is for <em>component subtree</em> context.</p>
</li>
<li><p><strong>Composables:</strong> For reusable, encapsulated logic. A composable can leverage <code>provide</code>/<code>inject</code> internally, but they solve different problems.</p>
</li>
</ul>
<p><code>provide</code>/<code>inject</code> shines for:</p>
<ul>
<li><p><strong>Theming or Configuration:</strong> Passing down global style settings or feature flags.</p>
</li>
<li><p><strong>Service Injection:</strong> Providing instances of helper classes (e.g., an analytics service, a logger).</p>
</li>
<li><p><strong>Component Library Context:</strong> When building UI components that need to implicitly share state (e.g., a <code>Tabs</code> component providing active tab state to <code>TabPanel</code> children).</p>
</li>
</ul>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p><code>provide</code> and <code>inject</code> are powerful tools in Vue 3 that help you manage data flow in complex component hierarchies, effectively solving "prop drilling." By understanding their reactivity behavior, using Symbols for keys, and providing sensible defaults, you can leverage them to build cleaner, more maintainable, and scalable Vue applications. Embrace them where appropriate, and keep your component communication clear!</p>
]]></content:encoded></item><item><title><![CDATA[Laravel 12.17.0: What's new]]></title><description><![CDATA[Laravel continues its commitment to developer ergonomics with the release of version 12.17.0. This minor update introduces a handful of impactful features that streamline common tasks, enhance data handling, and provide more powerful dependency injec...]]></description><link>https://afazkhatri.com/laravel-12170-whats-new</link><guid isPermaLink="true">https://afazkhatri.com/laravel-12170-whats-new</guid><category><![CDATA[Laravel]]></category><dc:creator><![CDATA[Afaz Khatri]]></dc:creator><pubDate>Thu, 05 Jun 2025 17:03:03 GMT</pubDate><content:encoded><![CDATA[<p>Laravel continues its commitment to developer ergonomics with the release of version 12.17.0. This minor update introduces a handful of impactful features that streamline common tasks, enhance data handling, and provide more powerful dependency injection capabilities. Let's delve into the key highlights of this release.</p>
<h3 id="heading-1-streamlined-querying-with-reorderdesc"><strong>1. Streamlined Querying with</strong> <code>reorderDesc()</code></h3>
<p>Querying databases is a daily ritual for Laravel developers, and the framework consistently seeks ways to make it more intuitive. Laravel 12.17.0 introduces the <code>reorderDesc()</code> method to the Query Builder, offering a more concise syntax for reordering query results in descending order.</p>
<p>The Problem It Solves:</p>
<p>Previously, if you needed to reorder a query (overriding any existing <code>orderBy</code> clauses) specifically in descending order, you'd typically use <code>reorder($column, 'desc')</code>. While functional, the explicit 'desc' string could be slightly verbose, especially in complex or conditionally ordered queries.</p>
<p>The <code>reorderDesc()</code> Solution:</p>
<p>The new method simplifies this by providing a dedicated helper for descending reordering.</p>
<p><strong>Before (Laravel &lt; 12.17.0):</strong></p>
<pre><code class="lang-php"><span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Models</span>\<span class="hljs-title">Product</span>;

<span class="hljs-comment">// Fetch products, initially ordered by 'name', but then reorder by 'price' in descending order.</span>
$expensiveProducts = Product::orderBy(<span class="hljs-string">'name'</span>)
    -&gt;reorder(<span class="hljs-string">'price'</span>, <span class="hljs-string">'desc'</span>)
    -&gt;get();

<span class="hljs-comment">// Or, a more complex scenario: Reordering posts by a subquery's result in descending order.</span>
$posts = Post::orderBy(<span class="hljs-string">'title'</span>)
    -&gt;when(
        Auth::check(),
        <span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params">$query</span>) =&gt;
        $<span class="hljs-title">query</span>-&gt;<span class="hljs-title">reorder</span>(<span class="hljs-params">
            Comment::select(<span class="hljs-params"><span class="hljs-string">'created_at'</span></span>)
                -&gt;whereColumn(<span class="hljs-params"><span class="hljs-string">'post_id'</span>, <span class="hljs-string">'posts.id'</span></span>)
                -&gt;where(<span class="hljs-params"><span class="hljs-string">'user_id'</span>, Auth::id(<span class="hljs-params"></span>)</span>)
                -&gt;orderByDesc(<span class="hljs-params"><span class="hljs-string">'created_at'</span></span>)
                -&gt;limit(<span class="hljs-params"><span class="hljs-number">1</span></span>),
            <span class="hljs-string">'desc'</span> // Explicit <span class="hljs-string">'desc'</span> here
        </span>)
    )-&gt;<span class="hljs-title">get</span>(<span class="hljs-params"></span>)</span>;
</code></pre>
<p><strong>After (Laravel 12.17.0):</strong></p>
<pre><code class="lang-php"><span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Models</span>\<span class="hljs-title">Product</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Models</span>\<span class="hljs-title">Post</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Models</span>\<span class="hljs-title">Comment</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Facades</span>\<span class="hljs-title">Auth</span>;

<span class="hljs-comment">// Simpler descending reordering of products by price.</span>
$expensiveProducts = Product::orderBy(<span class="hljs-string">'name'</span>)
    -&gt;reorderDesc(<span class="hljs-string">'price'</span>)
    -&gt;get();

<span class="hljs-comment">// Cleaner complex reordering:</span>
$posts = Post::orderBy(<span class="hljs-string">'title'</span>)
    -&gt;when(
        Auth::check(),
        <span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params">$query</span>) =&gt;
        $<span class="hljs-title">query</span>-&gt;<span class="hljs-title">reorderDesc</span>(<span class="hljs-params"> // Using reorderDesc(<span class="hljs-params"></span>)
            Comment::select(<span class="hljs-params"><span class="hljs-string">'created_at'</span></span>)
                -&gt;whereColumn(<span class="hljs-params"><span class="hljs-string">'post_id'</span>, <span class="hljs-string">'posts.id'</span></span>)
                -&gt;where(<span class="hljs-params"><span class="hljs-string">'user_id'</span>, Auth::id(<span class="hljs-params"></span>)</span>)
                -&gt;orderByDesc(<span class="hljs-params"><span class="hljs-string">'created_at'</span></span>)
                -&gt;limit(<span class="hljs-params"><span class="hljs-number">1</span></span>)
        </span>)
    )-&gt;<span class="hljs-title">get</span>(<span class="hljs-params"></span>)</span>;
</code></pre>
<p>This subtle addition improves code readability and conciseness, especially when dealing with dynamic or nested ordering logic.</p>
<h3 id="heading-2-enhanced-uri-handling-with-asuri-model-cast"><strong>2. Enhanced URI Handling with</strong> <code>AsUri</code> Model Cast</h3>
<p>Dealing with URLs in web applications is ubiquitous, from storing user profile links to external API endpoints. Laravel 12.17.0 introduces the <code>AsUri</code> model cast, which automatically transforms string attributes into <code>Illuminate\Support\Uri</code> instances and vice-versa. This powerful feature provides a structured and convenient way to interact with URI components.</p>
<p>The Problem It Solves:</p>
<p>Before AsUri, if you stored a URL as a string in your database, retrieving its components (like host, path, or query parameters) typically required manual string parsing or using PHP's parse_url() function, which could be cumbersome and error-prone.</p>
<p>The AsUri Solution:</p>
<p>By simply declaring an attribute with the AsUri cast in your Eloquent model, Laravel handles the conversion seamlessly. The underlying Illuminate\Support\Uri class (which extends Illuminate\Support\Stringable) provides a rich API for URI manipulation.</p>
<p>Real-World Example:</p>
<p>Consider a User model that stores a website_url and a profile_picture_cdn link, or a Project model with an external_repository_url.</p>
<pre><code class="lang-php"><span class="hljs-comment">// app/Models/User.php</span>
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Database</span>\<span class="hljs-title">Eloquent</span>\<span class="hljs-title">Model</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Database</span>\<span class="hljs-title">Eloquent</span>\<span class="hljs-title">Casts</span>\<span class="hljs-title">AsUri</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Uri</span>; <span class="hljs-comment">// To manually create Uri instances if needed</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Model</span>
</span>{
    <span class="hljs-keyword">protected</span> $casts = [
        <span class="hljs-string">'website_url'</span>       =&gt; AsUri::class,
        <span class="hljs-string">'profile_picture_cdn'</span> =&gt; AsUri::class,
    ];
}

<span class="hljs-comment">// In a controller or service:</span>
$user = User::find(<span class="hljs-number">1</span>);

<span class="hljs-comment">// Storing a URL:</span>
$user-&gt;website_url = <span class="hljs-string">'https://www.example.com/blog/my-article?category=tech&amp;id=123'</span>;
$user-&gt;profile_picture_cdn = <span class="hljs-string">'https://cdn.images.com/users/123/avatar.png'</span>;
$user-&gt;save();

<span class="hljs-comment">// Accessing the casted attribute:</span>
<span class="hljs-comment">// $user-&gt;website_url is now an instance of Illuminate\Support\Uri</span>
<span class="hljs-keyword">echo</span> $user-&gt;website_url-&gt;host();      <span class="hljs-comment">// Output: www.example.com</span>
<span class="hljs-keyword">echo</span> $user-&gt;website_url-&gt;path();      <span class="hljs-comment">// Output: /blog/my-article</span>
<span class="hljs-keyword">echo</span> $user-&gt;website_url-&gt;query();     <span class="hljs-comment">// Output: category=tech&amp;id=123</span>
<span class="hljs-keyword">echo</span> $user-&gt;website_url-&gt;scheme();    <span class="hljs-comment">// Output: https</span>
<span class="hljs-keyword">echo</span> $user-&gt;website_url-&gt;port();      <span class="hljs-comment">// Output: (empty string if default port)</span>
<span class="hljs-keyword">echo</span> $user-&gt;website_url-&gt;withQuery([<span class="hljs-string">'search'</span> =&gt; <span class="hljs-string">'laravel'</span>])-&gt;__toString();
<span class="hljs-comment">// Output: https://www.example.com/blog/my-article?search=laravel</span>

<span class="hljs-comment">// You can also compare Uri instances:</span>
<span class="hljs-keyword">if</span> ($user-&gt;profile_picture_cdn-&gt;host() === <span class="hljs-string">'cdn.images.com'</span>) {
    <span class="hljs-comment">// Logic for CDN assets</span>
}

<span class="hljs-comment">// The __toString() method allows direct string usage:</span>
<span class="hljs-keyword">echo</span> <span class="hljs-string">"Visit my website: "</span> . $user-&gt;website_url; <span class="hljs-comment">// Automatically converts to string</span>
</code></pre>
<p>This cast significantly improves type safety and provides a fluent API for working with URI data directly from your models, reducing boilerplate and potential errors.</p>
<h3 id="heading-3-powerful-dependency-injection-with-contextual-service-container-binding-via-php-attributes"><strong>3. Powerful Dependency Injection with Contextual Service Container Binding via PHP Attributes</strong></h3>
<p>Laravel's Service Container is a cornerstone of its architecture, enabling flexible dependency injection. Laravel 12.17.0 introduces an elegant new way to perform contextual binding using PHP attributes, making your container definitions even more declarative and localized.</p>
<p>The Problem It Solves:</p>
<p>Traditionally, contextual binding (where a specific implementation of an interface or class is injected based on the consumer) was configured using the when()-&gt;needs()-&gt;give() syntax within a Service Provider. While effective, this could sometimes lead to a centralized, verbose provider if many contextual bindings were needed.</p>
<p>The PHP Attribute Solution:</p>
<p>With the new #[ContextualBinding] attribute (or similar specific contextual attributes like #[Config], #[Auth], etc., which also leverage this mechanism), you can define these bindings directly on the constructor parameter where the dependency is needed.</p>
<p>Real-World Example:</p>
<p>Imagine you have an PaymentGatewayInterface and two implementations: StripePaymentGateway and PayPalPaymentGateway. You might want to use StripePaymentGateway for your main OrderProcessor but PayPalPaymentGateway for a specific SubscriptionManager.</p>
<pre><code class="lang-php"><span class="hljs-comment">// app/Contracts/PaymentGatewayInterface.php</span>
<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">Contracts</span>;

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">PaymentGatewayInterface</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">processPayment</span>(<span class="hljs-params"><span class="hljs-keyword">float</span> $amount</span>): <span class="hljs-title">bool</span></span>;
}

<span class="hljs-comment">// app/Services/StripePaymentGateway.php</span>
<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">Services</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Contracts</span>\<span class="hljs-title">PaymentGatewayInterface</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StripePaymentGateway</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">PaymentGatewayInterface</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">processPayment</span>(<span class="hljs-params"><span class="hljs-keyword">float</span> $amount</span>): <span class="hljs-title">bool</span> </span>{
        <span class="hljs-comment">// Stripe specific logic</span>
        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }
}

<span class="hljs-comment">// app/Services/PayPalPaymentGateway.php</span>
<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">Services</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Contracts</span>\<span class="hljs-title">PaymentGatewayInterface</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PayPalPaymentGateway</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">PaymentGatewayInterface</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">processPayment</span>(<span class="hljs-params"><span class="hljs-keyword">float</span> $amount</span>): <span class="hljs-title">bool</span> </span>{
        <span class="hljs-comment">// PayPal specific logic</span>
        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }
}

<span class="hljs-comment">// app/Services/OrderProcessor.php</span>
<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">Services</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Contracts</span>\<span class="hljs-title">PaymentGatewayInterface</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Container</span>\<span class="hljs-title">Attributes</span>\<span class="hljs-title">ContextualBinding</span>; <span class="hljs-comment">// Import the attribute</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OrderProcessor</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">
        #[ContextualBinding(<span class="hljs-params">implementation: StripePaymentGateway::<span class="hljs-keyword">class</span></span>)]
        PaymentGatewayInterface $paymentGateway // Inject Stripe here
    </span>) </span>{
        <span class="hljs-keyword">$this</span>-&gt;paymentGateway = $paymentGateway;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleOrder</span>(<span class="hljs-params"><span class="hljs-keyword">float</span> $amount</span>): <span class="hljs-title">bool</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>-&gt;paymentGateway-&gt;processPayment($amount);
    }
}

<span class="hljs-comment">// app/Services/SubscriptionManager.php</span>
<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">Services</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Contracts</span>\<span class="hljs-title">PaymentGatewayInterface</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Container</span>\<span class="hljs-title">Attributes</span>\<span class="hljs-title">ContextualBinding</span>; <span class="hljs-comment">// Import the attribute</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SubscriptionManager</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">
        #[ContextualBinding(<span class="hljs-params">implementation: PayPalPaymentGateway::<span class="hljs-keyword">class</span></span>)]
        PaymentGatewayInterface $paymentGateway // Inject PayPal here
    </span>) </span>{
        <span class="hljs-keyword">$this</span>-&gt;paymentGateway = $paymentGateway;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">manageSubscription</span>(<span class="hljs-params"><span class="hljs-keyword">float</span> $amount</span>): <span class="hljs-title">bool</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>-&gt;paymentGateway-&gt;processPayment($amount);
    }
}

<span class="hljs-comment">// No need for explicit 'when()-&gt;needs()-&gt;give()' in a Service Provider for these specific cases!</span>
</code></pre>
<p>This approach makes contextual bindings more explicit and local to where they are being used, leading to cleaner service providers and easier-to-understand dependency graphs. It leverages PHP 8's attribute syntax for a modern, declarative DI experience.</p>
<h3 id="heading-conclusion"><strong>Conclusion</strong></h3>
<p>Laravel 12.17.0 might be a minor release, but its additions are far from insignificant. The <code>reorderDesc()</code> method brings welcome conciseness to querying, the <code>AsUri</code> cast simplifies complex URI manipulations, and attribute-based contextual binding offers a powerful new paradigm for dependency injection. These features collectively contribute to Laravel's ongoing mission to provide an enjoyable and efficient development experience. We encourage all Laravel developers to explore these updates and integrate them into their projects to benefit from cleaner, more robust codebases.</p>
]]></content:encoded></item><item><title><![CDATA[Unleashing the Power of Named Middlewares in Laravel]]></title><description><![CDATA[Laravel, the PHP framework loved by developers worldwide, empowers you with a plethora of tools to build robust and scalable applications. One of these hidden gems that can greatly enhance your application's flexibility and organization is "Named Mid...]]></description><link>https://afazkhatri.com/unleashing-the-power-of-named-middlewares-in-laravel</link><guid isPermaLink="true">https://afazkhatri.com/unleashing-the-power-of-named-middlewares-in-laravel</guid><dc:creator><![CDATA[Afaz Khatri]]></dc:creator><pubDate>Wed, 08 Nov 2023 11:06:32 GMT</pubDate><content:encoded><![CDATA[<p>Laravel, the PHP framework loved by developers worldwide, empowers you with a plethora of tools to build robust and scalable applications. One of these hidden gems that can greatly enhance your application's flexibility and organization is "Named Middlewares." In this blog post, we'll dive deep into what named middlewares are, why they matter, and provide real-world examples to show you how to harness their potential to streamline your Laravel projects.</p>
<h3 id="heading-what-are-named-middlewares"><strong>What Are Named Middlewares?</strong></h3>
<p>Named middlewares in Laravel are a powerful way to enhance your application's security and control by attaching middleware to named routes or groups of routes. By assigning a unique name to your middleware, you can easily apply it to multiple routes, simplifying maintenance and reducing redundancy in your code.</p>
<h3 id="heading-the-importance-of-named-middlewares"><strong>The Importance of Named Middlewares</strong></h3>
<ol>
<li><p><strong>Code Organization</strong>: Named middlewares help you keep your codebase clean and well-structured. Instead of attaching the same middleware to multiple routes, you can simply reference the middleware by its name, making your code more concise and maintainable.</p>
</li>
<li><p><strong>Security and Access Control</strong>: With named middlewares, you can easily protect your routes from unauthorized access. Whether it's authentication, role-based permissions, or custom authorization logic, you can centralize security measures in a single middleware and apply it consistently across your application.</p>
</li>
</ol>
<h3 id="heading-how-to-define-named-middlewares"><strong>How to Define Named Middlewares</strong></h3>
<p>Let's get our hands dirty by diving into the code. Defining named middlewares in Laravel is straightforward. Here's an example of how to do it:</p>
<pre><code class="lang-php"><span class="hljs-comment">// In app/Http/Kernel.php</span>

<span class="hljs-keyword">protected</span> $routeMiddleware = [
    <span class="hljs-string">'auth'</span> =&gt; \App\Http\Middleware\Authenticate::class,
    <span class="hljs-string">'admin'</span> =&gt; \App\Http\Middleware\Admin::class,
    <span class="hljs-string">'api'</span> =&gt; \App\Http\Middleware\Api::class,
];
</code></pre>
<p>In this example, we've defined three named middlewares: 'auth,' 'admin,' and 'api.' Now, we can easily apply these named middlewares to our routes.</p>
<h3 id="heading-applying-named-middlewares-to-routes"><strong>Applying Named Middlewares to Routes</strong></h3>
<p>To apply a named middleware to a route, use the <strong>middleware</strong> method in your route definition. Here's an example:</p>
<pre><code class="lang-php"><span class="hljs-comment">// In routes/web.php</span>
Route::get(<span class="hljs-string">'/admin/dashboard'</span>, <span class="hljs-string">'AdminController@dashboard'</span>)
    -&gt;middleware(<span class="hljs-string">'auth'</span>, <span class="hljs-string">'admin'</span>);
</code></pre>
<p>In this example, we're applying the 'auth' and 'admin' middlewares to the '/admin/dashboard' route. It's that simple!</p>
<h3 id="heading-conclusion"><strong>Conclusion</strong></h3>
<p>Named middlewares in Laravel are a game-changer for developers looking to streamline their application code and improve security. By giving your middleware a name, you can easily attach it to routes, groups of routes, and even controller constructors. This approach not only improves code organization but also enhances the security of your application. So, the next time you're working on a Laravel project, don't forget to leverage the power of named middlewares to make your development process smoother and more secure. Happy coding!</p>
]]></content:encoded></item><item><title><![CDATA[Laravel Pint. What is it? Why do you need it? How to use it?]]></title><description><![CDATA[What is Laravel Pint?
Laravel Pint is a first-party package from the Laravel core team for PHP code style fixing. It is built on top of PHP-CS-Fixer and makes it simple to ensure your code style is clean and consistent.
Pint is installed by default o...]]></description><link>https://afazkhatri.com/laravel-pint-what-is-it-why-do-you-need-it-how-to-use-it</link><guid isPermaLink="true">https://afazkhatri.com/laravel-pint-what-is-it-why-do-you-need-it-how-to-use-it</guid><category><![CDATA[Laravel]]></category><category><![CDATA[PHP]]></category><category><![CDATA[Programming Tips]]></category><dc:creator><![CDATA[Afaz Khatri]]></dc:creator><pubDate>Tue, 18 Apr 2023 14:16:47 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-what-is-laravel-pint"><strong>What is Laravel Pint?</strong></h2>
<p><a target="_blank" href="https://laravel.com/docs/10.x/pint">Laravel Pint</a> is a first-party package from the Laravel core team for PHP code style fixing. It is built on top of PHP-CS-Fixer and makes it simple to ensure your code style is clean and consistent.</p>
<p>Pint is installed by default on the new Laravel applications, so you can use it immediately as soon as you create a new Laravel project.</p>
<h2 id="heading-why-do-you-need-it"><strong>Why do you need it?</strong></h2>
<p>This is an important question. Why do you really need Pint?</p>
<p>Your role as a developer on a project is to work on the solution that adds value to the project. And you should not keep going back and forth on formatting your code here and there, also not to mention to review those linting/formatting manually before the commits or merging a pull request.</p>
<p>So Pint or basically any linting tool takes this responsibility off your shoulders and allows you to think and work on solutions rather than wasting time on code styling and formatting.</p>
<p>With the clarification on why you need Pint on your project, let’s see how you can install and use Laravel Pint on your project.</p>
<h2 id="heading-how-to-install-and-use-laravel-pint-on-your-project"><strong>How to install and use Laravel Pint on your project?</strong></h2>
<p>I was thinking to add the process for installing Pint on the Laravel project, but as I was doing research for this post, I found that the new Laravel projects already have it installed by default. So you can use it without any effort on configuring it.</p>
<h3 id="heading-installation">Installation</h3>
<p>However, if you want to install it on your existing project, you may install Laravel Pint via Composer:</p>
<pre><code class="lang-bash">composer require laravel/pint --dev
</code></pre>
<h3 id="heading-formatting-code-using-pint">Formatting code using Pint</h3>
<p>By adding the composer package, the pint binary is added to your vendor/bin directory. You can run pint to fix your code style just by issuing the below command.</p>
<pre><code class="lang-bash">./vendor/bin/pint
</code></pre>
<p>Based on your preference you may only want to update the files that are changed. You can use the below command, it will fix the code styling for only the files that have uncommitted changes according to Git.</p>
<pre><code class="lang-bash">./vendor/bin/pint --dirty
</code></pre>
<p>You can find more details on configuring Pint according to your requirements on the <a target="_blank" href="https://laravel.com/docs/10.x/pint#configuring-pint">official Laravel Pint documentation</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Pint could be a very handy tool especially when you are working with teams. You can set up workflows that can detect code styling issues before merging a pull request. You can also set up the code styling rules that everyone should follow, and you can use Pint to validate that too.</p>
]]></content:encoded></item><item><title><![CDATA[Install Tailwind CSS with AdonisJS]]></title><description><![CDATA[Note: I advocate for Laravel projects most of the time, but was recently looking on how Adonis is doing, which is created from inspiration on Laravel and Rails. That is when this article comes to its being.

AdonisJS is a great Node.js framework. As ...]]></description><link>https://afazkhatri.com/install-tailwind-css-with-adonisjs</link><guid isPermaLink="true">https://afazkhatri.com/install-tailwind-css-with-adonisjs</guid><category><![CDATA[AdonisJS]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[Tailwind CSS]]></category><dc:creator><![CDATA[Afaz Khatri]]></dc:creator><pubDate>Tue, 18 Apr 2023 14:16:40 GMT</pubDate><content:encoded><![CDATA[<blockquote>
<p>Note: I advocate for Laravel projects most of the time, but was recently looking on how Adonis is doing, which is created from inspiration on Laravel and Rails. That is when this article comes to its being.</p>
</blockquote>
<p>AdonisJS is a great Node.js framework. As a developer you can just get started by using it for your next project. It is flexible and written using typescript.</p>
<p>Although, you can build great web project with Adonis with a very good speed, you can boost your development with Tailwind CSS which is gaining popularity in the web development industry. But there is no straight forward guide on how to install Tailwind CSS on Adonis projects. So in this article we will go through the steps to setup an Adonis project with Tailwind CSS.</p>
<h2 id="heading-create-your-project">Create your project</h2>
<p>Start by <a target="_blank" href="https://docs.adonisjs.com/guides/installation"><strong>creating a new AdonisJS project</strong></a> if you don’t have one set up already. Choose <strong>"web"</strong> when installer asks to select project structure. Press <strong>"y"</strong> when it asks <strong>"Configure webpack encore for compiling frontend assets?"</strong></p>
<pre><code class="lang-bash">npm init adonis-ts-app@latest my-project
<span class="hljs-built_in">cd</span> my-project
</code></pre>
<h2 id="heading-install-tailwind-css">Install Tailwind CSS</h2>
<p>Using npm, install tailwindcss and its peer dependencies, as well as postcss-loader, and then run the init command to generate both tailwind.config.js and postcss.config.js.</p>
<pre><code class="lang-bash">npm install -D tailwindcss postcss autoprefixer postcss-loader
npx tailwindcss init -p
</code></pre>
<h2 id="heading-enable-postcss-support">Enable PostCSS support</h2>
<p>In your webpack.config.js file, enable PostCSS Loader. See <a target="_blank" href="https://symfony.com/doc/current/frontend/encore/postcss.html"><strong>the documentation</strong></a> for more information.</p>
<pre><code class="lang-javascript">Encore
  <span class="hljs-comment">// ...</span>
  .enablePostCssLoader()
;
</code></pre>
<h2 id="heading-configure-your-template-paths">Configure your template paths</h2>
<p>Add the paths to all of your template files in your tailwind.config.js file.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">/** <span class="hljs-doctag">@type <span class="hljs-type">{import('tailwindcss').Config}</span> </span>*/</span>
<span class="hljs-built_in">module</span>.exports = {
  <span class="hljs-attr">content</span>: [
    <span class="hljs-string">"./resources/**/*.edge"</span>,
  ],
  <span class="hljs-attr">theme</span>: {
    <span class="hljs-attr">extend</span>: {},
  },
  <span class="hljs-attr">plugins</span>: [],
}
</code></pre>
<h2 id="heading-add-the-tailwind-directives-to-your-css">Add the Tailwind directives to your CSS</h2>
<p>Add the <code>@tailwind</code> directives for each of Tailwind’s layers to your ./resources/css/app.css file.</p>
<pre><code class="lang-css"><span class="hljs-keyword">@tailwind</span> base;
<span class="hljs-keyword">@tailwind</span> components;
<span class="hljs-keyword">@tailwind</span> utilities;
</code></pre>
<h2 id="heading-start-your-build-process">Start your build process</h2>
<p>Run your build process with npm run dev.</p>
<pre><code class="lang-bash">npm run dev
</code></pre>
<h2 id="heading-start-using-tailwind-in-your-project">Start using Tailwind in your project</h2>
<p>Make sure your compiled CSS is included in the &lt;head&gt; then start using Tailwind’s utility classes to style your content.</p>
<p>welcome.edge</p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!doctype <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span>&gt;</span>
  @entryPointStyles('app')
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-3xl font-bold underline"</span>&gt;</span>
    Hello world!
  <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>That's it. Your Adonis project is now ready. You can leverage the tailwind utilities in your project to create awesome interfaces.</p>
]]></content:encoded></item><item><title><![CDATA[Authenticating Vue Apollo Graphql with Laravel Sanctum]]></title><description><![CDATA[If you have been looking for a solution on how authenticating vue apollo graphql with laravel sanctum works with cookies and session, follow along.

This post assumes you are pretty well aware of how Laravel, Vuejs, and both with each other work. So ...]]></description><link>https://afazkhatri.com/authenticating-vue-apollo-graphql-with-laravel-sanctum</link><guid isPermaLink="true">https://afazkhatri.com/authenticating-vue-apollo-graphql-with-laravel-sanctum</guid><category><![CDATA[Vue.js]]></category><category><![CDATA[GraphQL]]></category><category><![CDATA[Programming Tips]]></category><dc:creator><![CDATA[Afaz Khatri]]></dc:creator><pubDate>Tue, 18 Apr 2023 14:16:14 GMT</pubDate><content:encoded><![CDATA[<p>If you have been looking for a solution on how authenticating vue apollo graphql with laravel sanctum works with cookies and session, follow along.</p>
<blockquote>
<p>This post assumes you are pretty well aware of how <a target="_blank" href="https://laravel.com/">Laravel</a>, <a target="_blank" href="https://vuejs.org/">Vuejs</a>, and both with each other work. So please follow along if you are looking for a solution to authenticate your Vue apollo frontend with <a target="_blank" href="https://laravel.com/docs/8.x/sanctum">Laravel Sanctum guard.</a></p>
</blockquote>
<p>Recently, I have been trying to setup Laravel Sanctum with my new project which uses a frontend of Vue js configured with vue router and apollo to work with graphql request.</p>
<h3 id="heading-sanctum-middleware">Sanctum Middleware</h3>
<p>Laravel Sanctum has a great middleware that you can apply on your Laravel backend to authenticate your frontend requests with your cookies.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707819577642/55ab8520-e489-4f12-9b37-81b4b24107dd.png" alt /></p>
<p>This middleware directly authenticates a user by session and cookies as it works in the out of the box authentication provided by Laravel.</p>
<p>Vue apollo uses fetch API to make requests to the backend and you can use any fetch options when configuring an <strong>httpLink</strong> for your vue apollo provider.</p>
<p>I was looking for solutions on the internet but could not find a clear solution on how this can be implemented for this specific scenario, so I am writing this article.</p>
<h3 id="heading-vue-apollo-setup">Vue apollo setup</h3>
<p>Below is the code snippet to configure standard apollo client for a vue application</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span>;
<span class="hljs-keyword">import</span> VueApollo <span class="hljs-keyword">from</span> <span class="hljs-string">'vue-apollo'</span>;

Vue.use(VueApollo);

<span class="hljs-keyword">import</span> { ApolloClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'apollo-client'</span>;
<span class="hljs-keyword">import</span> { createHttpLink } <span class="hljs-keyword">from</span> <span class="hljs-string">'apollo-link-http'</span>;
<span class="hljs-keyword">import</span> { InMemoryCache } <span class="hljs-keyword">from</span> <span class="hljs-string">'apollo-cache-inmemory'</span>;

<span class="hljs-keyword">const</span> httpLink = createHttpLink({ <span class="hljs-attr">uri</span>: <span class="hljs-string">'/api/graphql'</span>, }); <span class="hljs-comment">// The graphql endpoint url</span>

<span class="hljs-comment">// Cache implementation</span>
<span class="hljs-keyword">const</span> cache = <span class="hljs-keyword">new</span> InMemoryCache();

<span class="hljs-comment">// Create the apollo client</span>
<span class="hljs-keyword">const</span> apolloClient = <span class="hljs-keyword">new</span> ApolloClient({ <span class="hljs-attr">link</span>: httpLink, cache, });

<span class="hljs-comment">// Create the provider for Vue</span>
<span class="hljs-keyword">const</span> apolloProvider = <span class="hljs-keyword">new</span> VueApollo({ <span class="hljs-attr">defaultClient</span>: apolloClient, });

<span class="hljs-comment">// Initialize vue instance</span>
<span class="hljs-keyword">const</span> app = <span class="hljs-keyword">new</span> Vue({ <span class="hljs-attr">el</span>: <span class="hljs-string">'#app'</span>, apolloProvider }); <span class="hljs-comment">// Register the provider with Vue instance</span>
</code></pre>
<p>This configuration is useful when you want to create a GraphQL client without authenticating your requests. But if you want to authenticate your requests with Sanctum's <strong>EnsureFrontendRequestsAreStateful</strong> middleware, you have to make additional configurations.</p>
<p>By some research, I have been able to make an easy solution to authenticate requests with Sanctum sessions. Please check the below updated code.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span>;
<span class="hljs-keyword">import</span> VueApollo <span class="hljs-keyword">from</span> <span class="hljs-string">'vue-apollo'</span>;

Vue.use(VueApollo);

<span class="hljs-keyword">import</span> { ApolloClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'apollo-client'</span>;
<span class="hljs-keyword">import</span> { createHttpLink } <span class="hljs-keyword">from</span> <span class="hljs-string">'apollo-link-http'</span>;
<span class="hljs-keyword">import</span> { InMemoryCache } <span class="hljs-keyword">from</span> <span class="hljs-string">'apollo-cache-inmemory'</span>;
<span class="hljs-keyword">import</span> { setContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'apollo-link-context'</span>;

<span class="hljs-comment">// XSRF token is required to make post requests to your Laravel backend</span>
<span class="hljs-keyword">const</span> authLink = setContext(<span class="hljs-function">(<span class="hljs-params">_, { headers }</span>) =&gt;</span> { <span class="hljs-keyword">let</span> token = <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'XSRF-TOKEN[^;]+'</span>).exec(<span class="hljs-built_in">document</span>.cookie) token = <span class="hljs-built_in">decodeURIComponent</span>(token ? token.toString().replace(<span class="hljs-regexp">/^[^=]+./</span>, <span class="hljs-string">''</span>) : <span class="hljs-string">''</span>) <span class="hljs-keyword">return</span> { <span class="hljs-attr">headers</span>: { ...headers, <span class="hljs-string">'X-XSRF-TOKEN'</span>: token, }, }; });

<span class="hljs-keyword">const</span> httpLink = createHttpLink({ <span class="hljs-attr">uri</span>: <span class="hljs-string">'/api/graphql'</span>, <span class="hljs-attr">credentials</span>: <span class="hljs-string">'same-origin'</span>, }); <span class="hljs-comment">// The graphql endpoint url</span>

<span class="hljs-comment">// Cache implementation</span>
<span class="hljs-keyword">const</span> cache = <span class="hljs-keyword">new</span> InMemoryCache();

<span class="hljs-comment">// Create the apollo client</span>
<span class="hljs-keyword">const</span> apolloClient = <span class="hljs-keyword">new</span> ApolloClient({ <span class="hljs-attr">link</span>: authLink.concat(httpLink), cache, });

<span class="hljs-comment">// Create the provider for Vue</span>
<span class="hljs-keyword">const</span> apolloProvider = <span class="hljs-keyword">new</span> VueApollo({ <span class="hljs-attr">defaultClient</span>: apolloClient, });

<span class="hljs-comment">// Initialize vue instance</span>
<span class="hljs-keyword">const</span> app = <span class="hljs-keyword">new</span> Vue({ <span class="hljs-attr">el</span>: <span class="hljs-string">'#app'</span>, apolloProvider }); <span class="hljs-comment">// Register the provider with Vue instance</span>
</code></pre>
<p>These changes will allow your front end to send cookies with your frontend to your backend, so that the backend can verify the user's authentication by cookie/session.</p>
<p>This feature of Sanctum is very powerful when you want to create an SPA that works with your domain and that without exposing your backend to CSRF requests.</p>
<p>And that's what needs to be configured to authenticating a vue apollo graphql with laravel sanctum backend.</p>
]]></content:encoded></item><item><title><![CDATA[Becoming a (good) developer]]></title><description><![CDATA[Hello again. In this post, I will walk you through the topics which might be helpful to support your goal to become a good and successful developer.

This post assumes you are already at least an entry level developer regardless of the programming la...]]></description><link>https://afazkhatri.com/becoming-a-good-developer</link><guid isPermaLink="true">https://afazkhatri.com/becoming-a-good-developer</guid><category><![CDATA[Productivity]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Afaz Khatri]]></dc:creator><pubDate>Tue, 18 Apr 2023 14:16:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1707819573399/05b6e96b-ee06-4773-b5de-15c395101298.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hello again. In this post, I will walk you through the topics which might be helpful to support your goal to become a good and successful developer.</p>
<blockquote>
<p>This post assumes you are already at least an entry level developer regardless of the programming language.</p>
</blockquote>
<p>So, let's dive into the concepts to become a good developer.</p>
<h3 id="heading-learn-the-core-concepts">Learn the core concepts</h3>
<p>The core concepts of programming in general is helpful no matter which programming language background you are from. Learning the core concepts of the programming in general or for a specific programming language can help you boost your confidence, and it can also leverage your skills on how you can approach to a problem by simply applying the concepts.</p>
<p>For example, if you belong to the php programming background. You should checkout its core concepts, like, data types (variables), conditional statements (if/else/else if), control statements (for/foreach/while/do..while), OOP (Object oriented programming) concepts. Object oriented programming concepts are similar for most of the programming languages.</p>
<p>Keep in mind, if you have concepts clear for one programming language, you can easily adopt another programming language. I can say this by my experience. I have been a php developer since last 3 years, and in those last 3 years I have learned too many different things about the workings of php programming language and the core concepts behind it. And since last 1 year, I was able to adopt javascript and dart (used in flutter). Which is great in comparison of learning php in 3 years and other 2 programming languages in just 1 year.</p>
<p>So take this seriously, take time to learn about the programming language you are engaged into.</p>
<h3 id="heading-read-code">Read Code</h3>
<p>For new developers, this point may seem like, what the hell. Why should I read code while I should be typing it. But, reading code is a good practice to improve your skills and is followed my most of the experienced developers.</p>
<p>Where should you read the code ? Github....😊.</p>
<p>As a developer you might have used some kind of library. Is it worth studying the library ? Of course. Go ahead and check the code of any library you might have used. You may be surprised what approaches can be used to solve a problem differently. By reading others' code you can learn new techniques to acheive something more efficiently. Bonus, you can undestand how the library works, which at some point of time is useful, because as a developer you may need a customized solution with some functionality of a library.</p>
<p>If you are going to work on an existing project, take it as an opportunity to read the code someone else has wrote. Reading code is a good practice and should be considered important on your journey towards becoming a good developer.</p>
<p>P.S. Learning by mistakes is a good thing, and learning by others' mistakes is even better. Reading others' code can help you avoid the mistakes they might have made.</p>
<h3 id="heading-write-readable-code-well">Write readable code (well)</h3>
<p>Along with reading the code of others, it is also important to write the readable code.</p>
<p>How can I make my code readable ?</p>
<ul>
<li><p>Use appropriate names for variables, methods and functions.</p>
</li>
<li><p>Split each method and function so that each method have single responsibility.</p>
</li>
<li><p>Splitting method per responsibility can also help in implementing DRY (Don't repeat yourself) concept.</p>
</li>
<li><p>Avoid concurrency. (Don't write code that works in the same way for different places, instead make a single place more capable and responsible for the task).</p>
</li>
<li><p>If you are going to create classes which in core have the same architecture but corresponds to different entities create an abstact class for them instead of creating the classes with same properties and methods.</p>
</li>
<li><p>Create trait classes if you are attaching functionality to more than one class.</p>
</li>
</ul>
<p>The points above are the core ideas, it may differ from the view point of the programming language you might belong to, but every programming language have support for writing code using these approaches.</p>
<p>Why should I write readable code ?</p>
<p>No one would like to work on the code which can not be understood. Even you will curse the developer who might have wrote code that is not readable. So the sake of the art of development, write code that is readable and understadable, so that anyone can undestand your code and can start working on it asap.</p>
<h3 id="heading-learn-techniques-not-tools">Learn techniques, not tools</h3>
<p>Tools help you to find your way around the problem, but techniques will always stay besides you no matter what tools/programming language you use. Tools come and go. It is good to get familier with the tools you use but don't rely on them.</p>
<p>Where can I learn techniques ?</p>
<p>Out there, in this open source world, there are plenty of implementation in libraries, projects of different techniques. Read code, find different techniques inside them. Here, above discussed point <strong>Read Code</strong> makes more sense. Follow good developers on Twitter, follow blogs which publishes this kind of articles.</p>
<p>Learning is a never ending process, but ultimately it makes you better overtime.</p>
<h3 id="heading-share-the-knowledge">Share the knowledge</h3>
<p>Are you afraid of forgetting the concepts you might have learned ? Here is my tip for making them permenant part of yourself.</p>
<p>Sharing what you know.</p>
<p>Teaching what you have learned to other developers is a good practice. Teaching is a process where your mind needs to be precise. And don't take it as a responsibility, but take it as a goodwill of your knowledge. The knowledge you have aquired was ultimately shared by someone else. So act your part. Share what you have learned.</p>
<p>Sharing your knowledge makes the learned concepts concrete. Teaching process needs clear knowledge of the concept you are going to teach. So your mind automatically does the process of clearing the concepts if it were not already before you teach it to someone else.</p>
<h3 id="heading-be-responsible">Be responsible</h3>
<p>Take responsibility of your work and/or your teams' work. If there has been some fault because of you, take responsibility of the fault. Rectify your mistakes and resolve them.</p>
<p>This is a very important process, beacause taking responsibility of your mistakes, and resolving them will make you more vigilant before making similar kind of faults/problems, also you will have a solution if you have already resolved similar kind of problems.</p>
<p>This process will also make you more confident. Also you will be in possesion of new wits with each mistake. 😇</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>Being a (good) developer is not a milestone, its a process. You have to stay with the principles whichever helps your become better, either some from this article or from anywhere else.</p>
<p>Let me know, if I have missed anything in the comments.</p>
<p>Photo by <a target="_blank" href="https://unsplash.com/@anniespratt?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Annie Spratt</a> on <a target="_blank" href="https://unsplash.com/s/photos/developer?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Productive you]]></title><description><![CDATA[There are plenty of articles that can guide you to be more productive, But this post is the outcome of the actual my actual experiments with different approaches and tools.
First things first.
Find your concentration
First of all, before using approa...]]></description><link>https://afazkhatri.com/productive-you</link><guid isPermaLink="true">https://afazkhatri.com/productive-you</guid><category><![CDATA[Productivity]]></category><dc:creator><![CDATA[Afaz Khatri]]></dc:creator><pubDate>Tue, 18 Apr 2023 14:15:55 GMT</pubDate><content:encoded><![CDATA[<p>There are plenty of articles that can guide you to be more productive, But this post is the outcome of the actual my actual experiments with different approaches and tools.</p>
<p>First things first.</p>
<h3 id="heading-find-your-concentration">Find your concentration</h3>
<p>First of all, before using approaches and tools, identify what is distracting you from concentrating.</p>
<p><a target="_blank" href="http://blog.idonethis.com/distractions-at-work/">It takes an average of about 25 minutes (23 minutes and 15 seconds, to be exact) to return to the original task after an interruption, according to Gloria Mark, who studies digital distraction at the University of California, Irvine.</a></p>
<p>So take time to make a list of distractions that breaks your concentration now and then. This list might contain your dinging phone, people moving by you, or anything else that you think is taking your concentration away. Make sure this distractions don't take your concentration away unless important.</p>
<p>Sometimes it happens you are working on something important and you have a thought that also needs attention, and your mind drifts towards that other thought and then this happens again with another different thought which again does the same. It breaks you from focusing on one thing and keeps your mind swirling between one thought and another.</p>
<p>Here comes our next friend to help us clear thing.</p>
<h3 id="heading-write-down-in-between-thoughts">Write down in between thoughts</h3>
<p>Do you think it is alright to discard your thoughts of something else, while your are working on whole different thing. I think it is not.</p>
<p>I prefer writing my in between thoughts, so that my mind let me focus on my current task. And as I have jotted down my thoughts in between, I have the ability to think and prioritize those tasks and even discard some of them at a later point of time. But it is a good practice of having a record of your in between thoughts so that you have something to think of when your mind is free from one task.</p>
<p>Here comes our next friend towards productivity.</p>
<p>Use tools that help you track the tasks and thoughts.</p>
<h3 id="heading-collaboration-tools">Collaboration tools</h3>
<p>Collaboration tools help you track the progress of tasks and the current status of overall process. Although its best suited to teams, its really helpful for individuals.</p>
<p>We just talked about writing the in between thoughts, you can use online tools like Trello to make the list of thoughts. Trello also helps you realize the process of your end product. So once you have your list with ideas in the board, you can at any point of time decide if you want to work on this, or want to work on it later, it needs some kind of research or you want to discard it.</p>
<p>Using Trello or any other visualized project management system opens up a birds eye view with eagle's eyes for you. I will not go into deep how Trello works, but here is simple explanation.</p>
<p>In Trello, there are two thing which we will take into account for our approach. Lists and Cards. Lists are columns which contatins cards. Think of lists as a part of process to realize your ides. And cards are the thoughts/tasks which eventually gets realized.</p>
<p>See the image:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707819564236/5f7f27ca-5153-42ce-bf3d-68fd3efa1c4d.png" alt /></p>
<p>Sometimes a thought has a very large scope and needs to be broken down into smaller pieces. You can even create separate cards with broken down pieces of the actual idea. This helps you concentrate on the smaller part and let you earn the small wins to achieve your goal.</p>
<p>Trello is just an example here, you can use whichever tool you prefer, even a notebook and pencil is enough. The process is important.</p>
<h3 id="heading-find-your-corner">Find your corner</h3>
<p>The title for this section, is just out from mind. But the concept has strong impact on your productivity.</p>
<p>Choose your place to work, and stick with the place. Do not do other things on your workplace. As of writing this article, most of the developers are working from home. And working from home is good but has an impact on your productivity if you are not able to separate your work and your home.</p>
<p>So, choose your place to work where you can work comfortably. Regularly use the same place and settings to work, it generates you an environment for your work. Studies find that people tend to stay focused for longer durations if they have the maintained environment. Meaning you can create your own work environment. Your mind will automatically let you focus on your work, as it knows that you regularly work in this environment.</p>
<p>Let me know, if the tips were helpful or not.</p>
<p>Thanks for getting until here. This is my very first article. If you like it, please share it. Also let me know if I have made mistakes in the article, I am learning to create the content that can help people.</p>
]]></content:encoded></item></channel></rss>