<?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: K B Zaman</title>
    <description>The latest articles on DEV Community by K B Zaman (@kbzaman2).</description>
    <link>https://dev.to/kbzaman2</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F551726%2F99328f81-e61e-4ced-bd40-133509960e1f.png</url>
      <title>DEV Community: K B Zaman</title>
      <link>https://dev.to/kbzaman2</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kbzaman2"/>
    <language>en</language>
    <item>
      <title>Case Study: How I Built a Modular Laravel CMS with Addons, Themes &amp; Dynamic Loading</title>
      <dc:creator>K B Zaman</dc:creator>
      <pubDate>Fri, 07 Aug 2026 15:14:40 +0000</pubDate>
      <link>https://dev.to/kbzaman2/case-study-how-i-built-a-modular-laravel-cms-with-addons-themes-dynamic-loading-pea</link>
      <guid>https://dev.to/kbzaman2/case-study-how-i-built-a-modular-laravel-cms-with-addons-themes-dynamic-loading-pea</guid>
      <description>&lt;p&gt;Most Laravel CMS projects start clean.&lt;/p&gt;

&lt;p&gt;Then you add a blog.&lt;/p&gt;

&lt;p&gt;Then a contact form.&lt;/p&gt;

&lt;p&gt;Then multilingual support, analytics, cookie consent, newsletter subscriptions, SEO settings, custom pages...&lt;/p&gt;

&lt;p&gt;Before long, the "core" knows about everything.&lt;/p&gt;

&lt;p&gt;I wanted to build the opposite.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Laravel Addon CMS&lt;/strong&gt; is an open-source CMS built with Laravel 12 where the core stays intentionally small, product features live inside installable addons, and themes completely own the public-facing website.&lt;/p&gt;

&lt;p&gt;Instead of starting every new project by copying the previous Laravel project, the idea is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Build the website by composing reusable features rather than forking an existing codebase.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Problem I Wanted to Solve
&lt;/h2&gt;

&lt;p&gt;I've seen the same pattern repeatedly in Laravel projects.&lt;/p&gt;

&lt;p&gt;A feature starts reusable, but eventually becomes tightly coupled to a specific project.&lt;/p&gt;

&lt;p&gt;A blog module gets mixed into the main application.&lt;/p&gt;

&lt;p&gt;A contact form gets rewritten.&lt;/p&gt;

&lt;p&gt;Theme sections become one-off Blade files.&lt;/p&gt;

&lt;p&gt;Analytics code gets scattered around layouts.&lt;/p&gt;

&lt;p&gt;Then a bug gets fixed in one project while five older projects continue running the previous version.&lt;/p&gt;

&lt;p&gt;The problem isn't necessarily Laravel.&lt;/p&gt;

&lt;p&gt;The problem is &lt;strong&gt;where we draw the boundaries&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For Laravel Addon CMS, I decided on three major boundaries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Core
├── Shared CMS infrastructure
│
Addons
├── Product features
│
Themes
└── Website presentation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The core shouldn't need to know what features developers will build in the future.&lt;/p&gt;




&lt;h1&gt;
  
  
  What the Core Owns
&lt;/h1&gt;

&lt;p&gt;The CMS core handles the things almost every website needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Admin authentication&lt;/li&gt;
&lt;li&gt;Media management&lt;/li&gt;
&lt;li&gt;Pages&lt;/li&gt;
&lt;li&gt;SEO settings&lt;/li&gt;
&lt;li&gt;Database-backed settings&lt;/li&gt;
&lt;li&gt;Theme customization&lt;/li&gt;
&lt;li&gt;Addon installation&lt;/li&gt;
&lt;li&gt;Addon lifecycle management&lt;/li&gt;
&lt;li&gt;File handling&lt;/li&gt;
&lt;li&gt;Shared helpers&lt;/li&gt;
&lt;li&gt;Dynamic addon/theme loading&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything outside that shared infrastructure can become an addon or part of a theme.&lt;/p&gt;

&lt;p&gt;The project currently uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Laravel 12
PHP 8.2+
MySQL
Blade
Composer
Vite
Bootstrap
Artisan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  The Interesting Part: The Database Decides What Laravel Loads
&lt;/h1&gt;

&lt;p&gt;This is probably the architectural decision I like most about the project.&lt;/p&gt;

&lt;p&gt;Normally, Laravel service providers are registered through application configuration.&lt;/p&gt;

&lt;p&gt;But if an addon can be installed, enabled, disabled, or removed through the admin panel, I don't want developers manually editing configuration every time.&lt;/p&gt;

&lt;p&gt;So after installation, the application reads the active addons from the database.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Application boots
      ↓
Check CMS tables
      ↓
Read active addons
      ↓
Find addon ServiceProviders
      ↓
Register providers
      ↓
Read active theme
      ↓
Register theme ServiceProvider
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Addons live here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/
└── Addons/
    ├── PostCraft/
    ├── MailMate/
    └── ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Themes live here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/
└── Themes/
    ├── Brixly/
    ├── YourTheme/
    └── ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means enabling an addon isn't just changing a boolean that the UI checks.&lt;/p&gt;

&lt;p&gt;It changes what Laravel actually boots.&lt;/p&gt;

&lt;p&gt;The addon provider can determine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which routes exist&lt;/li&gt;
&lt;li&gt;Which controllers become available&lt;/li&gt;
&lt;li&gt;Which views are registered&lt;/li&gt;
&lt;li&gt;Which sidebar items appear&lt;/li&gt;
&lt;li&gt;Which frontend sections become available&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same idea applies to themes.&lt;/p&gt;

&lt;p&gt;Switch the active theme and its provider becomes responsible for registering the public website.&lt;/p&gt;




&lt;h1&gt;
  
  
  An Addon Is Basically a Laravel Feature Package
&lt;/h1&gt;

&lt;p&gt;I deliberately avoided creating an entirely new framework developers would have to learn.&lt;/p&gt;

&lt;p&gt;If you know Laravel, the structure should already feel familiar.&lt;/p&gt;

&lt;p&gt;A typical addon can contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/Addons/Blog/
├── BlogServiceProvider.php
├── Activator.php
├── composer.json
├── routes/
├── controllers/
├── models/
├── views/
├── assets/
└── database/
    └── migrations/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each addon owns its feature.&lt;/p&gt;

&lt;p&gt;That means routes, controllers, models, migrations and views don't have to leak into the main application.&lt;/p&gt;




&lt;h1&gt;
  
  
  Scaffolding an Addon
&lt;/h1&gt;

&lt;p&gt;I also wanted addon development to feel similar to normal Laravel development.&lt;/p&gt;

&lt;p&gt;The project uses the &lt;code&gt;cmsaddoncommands&lt;/code&gt; package to provide Artisan commands for scaffolding.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create the addon&lt;/span&gt;
php artisan make:addon Blog

&lt;span class="c"&gt;# Create an addon model&lt;/span&gt;
php artisan addon:model Blog Post &lt;span class="nt"&gt;-m&lt;/span&gt;

&lt;span class="c"&gt;# Create a controller&lt;/span&gt;
php artisan addon:controller Blog PostController

&lt;span class="c"&gt;# Create an addon migration&lt;/span&gt;
php artisan addon:migration Blog create_posts_table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Addon migrations can also be handled independently:&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 addon:migrate Blog

php artisan addon:migrate:rollback Blog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps database changes attached to the feature that owns them.&lt;/p&gt;




&lt;h1&gt;
  
  
  Registering Routes, Views and Admin Navigation
&lt;/h1&gt;

&lt;p&gt;An addon ServiceProvider can look something like this:&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="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Addons\Blog&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\Lib\Sidenav&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\ServiceProvider&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;BlogServiceProvider&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ServiceProvider&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="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;loadRoutesFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;__DIR__&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'/routes/cms_blog.php'&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;loadViewsFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;__DIR__&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'/views'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'Blog'&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;Sidenav&lt;/span&gt;&lt;span class="o"&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;'Content'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'Blog posts'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'admin.blog.index'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'ph ph-article'&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;Nothing particularly magical is happening here.&lt;/p&gt;

&lt;p&gt;And that's intentional.&lt;/p&gt;

&lt;p&gt;It's still Laravel.&lt;/p&gt;

&lt;p&gt;The CMS mainly provides conventions and lifecycle management around familiar Laravel concepts.&lt;/p&gt;




&lt;h1&gt;
  
  
  Addon Lifecycle Management
&lt;/h1&gt;

&lt;p&gt;Installable addons create another problem:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens to their database structure when they're activated or removed?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each addon can provide an &lt;code&gt;Activator&lt;/code&gt; class with lifecycle hooks for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;activate
deactivate
delete
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During activation, the CMS can run migrations belonging specifically to that addon before marking it active.&lt;/p&gt;

&lt;p&gt;During deletion, it can:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Roll back addon migrations.&lt;/li&gt;
&lt;li&gt;Execute the addon delete hook.&lt;/li&gt;
&lt;li&gt;Remove its files.&lt;/li&gt;
&lt;li&gt;Remove its database record.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The lifecycle stays intentionally simple.&lt;/p&gt;

&lt;p&gt;Laravel developers already understand migrations and Artisan, so I didn't want another abstraction hiding them.&lt;/p&gt;




&lt;h1&gt;
  
  
  Addon Metadata and Dependencies
&lt;/h1&gt;

&lt;p&gt;Each addon also contains metadata describing itself.&lt;/p&gt;

&lt;p&gt;When distributing an addon, things like its nickname, version and dependencies matter.&lt;/p&gt;

&lt;p&gt;For example, an addon may declare:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;required_addons
required_system_version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are a few conventions I try to keep strict:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Addon nickname should match its folder/provider naming.&lt;/li&gt;
&lt;li&gt;Database changes belong inside the addon.&lt;/li&gt;
&lt;li&gt;Addons should use their own view namespaces.&lt;/li&gt;
&lt;li&gt;Dependencies should be declared before distribution.&lt;/li&gt;
&lt;li&gt;Lifecycle hooks should only handle work migrations can't handle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These restrictions make addons easier to move between projects.&lt;/p&gt;




&lt;h1&gt;
  
  
  Themes Are More Than Blade Templates
&lt;/h1&gt;

&lt;p&gt;I didn't want themes to mean:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Change a CSS file and replace some Blade templates."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A theme should own the actual website presentation.&lt;/p&gt;

&lt;p&gt;A theme can contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/Themes/YourTheme/
├── YourThemeServiceProvider.php
├── routes/
├── controllers/
├── Lib/
├── views/
│   ├── layouts/
│   ├── sections/
│   └── slices/
├── assets/
├── config.json
└── screenshot.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The interesting directory here is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Lib/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It contains the definitions for configurable website sections.&lt;/p&gt;




&lt;h1&gt;
  
  
  Building Configurable Theme Sections
&lt;/h1&gt;

&lt;p&gt;Imagine a theme has a hero section.&lt;/p&gt;

&lt;p&gt;Instead of hardcoding its content into Blade, the theme can describe the fields that should be editable.&lt;/p&gt;

&lt;p&gt;For example:&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="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Themes\YourTheme\Lib&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;HeroSection&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;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$themeConfig&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="nv"&gt;$themeConfig&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addSection&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="s1"&gt;'key'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'hero_section'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'pages'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'home'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s1"&gt;'position'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'title'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hero Section'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="nv"&gt;$themeConfig&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'hero_section'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'type'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'text'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'key'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'heading'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'label'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Heading'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'default'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Build something useful'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="nv"&gt;$themeConfig&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'hero_section'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'type'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'image'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'key'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'image'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'label'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hero Image'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'size'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'1200x800'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'accept'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'.png,.jpg,.jpeg,.webp'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="nv"&gt;$themeConfig&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'hero_section'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'type'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'url'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'key'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'button_url'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'label'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Button URL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'attr'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'href'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'default'&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="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;Now the CMS understands that the section contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Heading → text
Image   → image
Button  → URL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The admin customizer can generate editing controls from those definitions.&lt;/p&gt;




&lt;h1&gt;
  
  
  Rendering the Section
&lt;/h1&gt;

&lt;p&gt;The corresponding Blade file might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;section class="hero-section"&amp;gt;
    &amp;lt;div class="container"&amp;gt;

        &amp;lt;div class="hero-content"&amp;gt;
            &amp;lt;h1&amp;gt;
                &amp;lt;x-ui.text
                    section="hero_section"
                    key="heading"
                /&amp;gt;
            &amp;lt;/h1&amp;gt;

            &amp;lt;x-ui.a
                class="btn"
                section="hero_section"
                key="button_url"
            &amp;gt;
                Learn more
            &amp;lt;/x-ui.a&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;x-ui.img
            class="img-fluid"
            section="hero_section"
            key="image"
            alt="Hero image"
        /&amp;gt;

    &amp;lt;/div&amp;gt;
&amp;lt;/section&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These components resolve the saved theme content while preserving the editing hooks required by the CMS customizer.&lt;/p&gt;

&lt;p&gt;So the flow becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Section PHP class
        ↓
Defines editable fields
        ↓
Admin customizer
        ↓
User edits content
        ↓
Content stored as JSON
        ↓
Blade UI components
        ↓
Public website
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives theme developers control over presentation without requiring site owners to edit Blade.&lt;/p&gt;




&lt;h1&gt;
  
  
  Repeaters and Dynamic Content
&lt;/h1&gt;

&lt;p&gt;Some sections aren't simple fields.&lt;/p&gt;

&lt;p&gt;Think about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Testimonials&lt;/li&gt;
&lt;li&gt;Client logos&lt;/li&gt;
&lt;li&gt;Services&lt;/li&gt;
&lt;li&gt;Team members&lt;/li&gt;
&lt;li&gt;Pricing cards&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These need repeatable groups.&lt;/p&gt;

&lt;p&gt;The theme API therefore supports repeater definitions, while their frontend templates can live under:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;views/slices/{section_key}/{repeater_key}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The theme controls how repeated items look, while the CMS controls how their content is edited and stored.&lt;/p&gt;




&lt;h1&gt;
  
  
  Addons Can Also Push Frontend Sections
&lt;/h1&gt;

&lt;p&gt;This was another important requirement.&lt;/p&gt;

&lt;p&gt;Suppose I create a newsletter addon.&lt;/p&gt;

&lt;p&gt;The addon shouldn't only provide:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/admin/subscribers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It might also provide a reusable newsletter signup section.&lt;/p&gt;

&lt;p&gt;That section could then be inserted into a supported theme page.&lt;/p&gt;

&lt;p&gt;This lets feature addons participate in the frontend without owning the entire theme.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MailMate Addon
│
├── Subscriber management
├── Newsletter logic
└── Newsletter section
          ↓
       Theme page
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The feature remains owned by the addon while presentation remains compatible with the theme system.&lt;/p&gt;




&lt;h1&gt;
  
  
  Why Service Providers Were the Right Boundary
&lt;/h1&gt;

&lt;p&gt;I considered creating a more custom module-loading system.&lt;/p&gt;

&lt;p&gt;But Laravel already has a good extension boundary:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Service Providers.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;They can register:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Routes&lt;/li&gt;
&lt;li&gt;Views&lt;/li&gt;
&lt;li&gt;Bindings&lt;/li&gt;
&lt;li&gt;Configuration&lt;/li&gt;
&lt;li&gt;Boot logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So rather than hiding Laravel, the CMS uses Laravel itself as much as possible.&lt;/p&gt;

&lt;p&gt;That's an architectural principle I've tried to maintain throughout the project:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Add conventions around Laravel instead of replacing Laravel concepts.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A developer shouldn't need to learn a private mini-framework just to build a CMS addon.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Trade-Off: Architecture Got More Attention Than UI
&lt;/h1&gt;

&lt;p&gt;One thing I'm very aware of is that the current UI/UX isn't the strongest part of the project.&lt;/p&gt;

&lt;p&gt;Most of the early work went into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Addon boundaries&lt;/li&gt;
&lt;li&gt;Dynamic provider registration&lt;/li&gt;
&lt;li&gt;Theme registration&lt;/li&gt;
&lt;li&gt;Migration lifecycle&lt;/li&gt;
&lt;li&gt;Content configuration&lt;/li&gt;
&lt;li&gt;Installation&lt;/li&gt;
&lt;li&gt;Developer tooling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That produced a system I'm happier extending, but it also means the admin interface still needs work.&lt;/p&gt;

&lt;p&gt;The customizer, media manager, addon management and theme controls could all be cleaner and more polished.&lt;/p&gt;

&lt;p&gt;I don't see that as an architectural problem.&lt;/p&gt;

&lt;p&gt;The foundation is there.&lt;/p&gt;

&lt;p&gt;The next stage is making that architecture pleasant for non-technical users too.&lt;/p&gt;




&lt;h1&gt;
  
  
  What I Would Keep
&lt;/h1&gt;

&lt;p&gt;If I rebuilt the project today, I would absolutely keep the separation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Core → infrastructure

Addons → features

Themes → presentation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'd also keep the Laravel-native approach.&lt;/p&gt;

&lt;p&gt;Service providers, Blade, migrations, route files, Composer metadata and Artisan commands are already familiar to Laravel developers.&lt;/p&gt;

&lt;p&gt;That's valuable.&lt;/p&gt;




&lt;h1&gt;
  
  
  What I Would Improve
&lt;/h1&gt;

&lt;p&gt;There are several things I'd invest more time in next.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Admin UI/UX
&lt;/h3&gt;

&lt;p&gt;The functionality exists, but workflows can be more intuitive and visually consistent.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Automated Tests
&lt;/h3&gt;

&lt;p&gt;Especially around:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Install addon
Activate addon
Deactivate addon
Delete addon
Run migrations
Rollback migrations
Dependency validation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These lifecycle operations deserve stronger automated coverage.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Theme API Documentation
&lt;/h3&gt;

&lt;p&gt;The section system becomes much easier to use once you understand it, but that understanding shouldn't require reading the source.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Smaller Demo Data
&lt;/h3&gt;

&lt;p&gt;A smaller default installation would make the architecture easier for new contributors to explore.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Contributor Experience
&lt;/h3&gt;

&lt;p&gt;I'd like the path from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my first addon
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to be extremely short.&lt;/p&gt;




&lt;h1&gt;
  
  
  It's Open Source
&lt;/h1&gt;

&lt;p&gt;Laravel Addon CMS is released under the &lt;strong&gt;MIT License&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I'm especially interested in contributions around:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UI/UX improvements&lt;/li&gt;
&lt;li&gt;Documentation&lt;/li&gt;
&lt;li&gt;Automated tests&lt;/li&gt;
&lt;li&gt;Accessibility&lt;/li&gt;
&lt;li&gt;Bug fixes&lt;/li&gt;
&lt;li&gt;Validation&lt;/li&gt;
&lt;li&gt;Theme sections&lt;/li&gt;
&lt;li&gt;New themes&lt;/li&gt;
&lt;li&gt;Focused addons&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I prefer small, understandable pull requests over huge rewrites.&lt;/p&gt;

&lt;p&gt;One addon.&lt;/p&gt;

&lt;p&gt;One section.&lt;/p&gt;

&lt;p&gt;One admin workflow.&lt;/p&gt;

&lt;p&gt;One failing test.&lt;/p&gt;

&lt;p&gt;One documentation gap.&lt;/p&gt;

&lt;p&gt;Those improvements compound quickly in an extensible system.&lt;/p&gt;




&lt;h1&gt;
  
  
  Final Thoughts
&lt;/h1&gt;

&lt;p&gt;The biggest lesson from building this project wasn't how to create a CMS.&lt;/p&gt;

&lt;p&gt;It was about &lt;strong&gt;boundaries&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The difficult part of an extensible system isn't adding features.&lt;/p&gt;

&lt;p&gt;It's deciding what should &lt;strong&gt;not&lt;/strong&gt; know about those features.&lt;/p&gt;

&lt;p&gt;For Laravel Addon CMS, the answer became:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The core provides infrastructure.
Addons provide capabilities.
Themes provide presentation.
The database decides what is active.
Laravel does the rest.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is still plenty to improve, especially around UI/UX, tests and documentation.&lt;/p&gt;

&lt;p&gt;But I think the architecture is moving in the right direction: a CMS where building the next Laravel website means assembling reusable pieces instead of copying the previous project.&lt;/p&gt;

&lt;p&gt;If you're a Laravel developer, I'd be interested to hear how you approach modularity in larger applications.&lt;/p&gt;

&lt;p&gt;Do you prefer packages, modules, domains, plugins—or something else?&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Project:&lt;/strong&gt; Laravel Addon CMS&lt;br&gt;
&lt;strong&gt;Stack:&lt;/strong&gt; Laravel 12, PHP, MySQL, Blade, Composer, Vite, Bootstrap&lt;br&gt;
&lt;strong&gt;License:&lt;/strong&gt; MIT&lt;br&gt;
&lt;strong&gt;Source:&lt;/strong&gt; &lt;a href="https://github.com/kbzaman76/laravel-cms" rel="noopener noreferrer"&gt;https://github.com/kbzaman76/laravel-cms&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally written from my experience designing and building Laravel Addon CMS.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Content rewriting, editing, and formatting assistance provided by ChatGPT.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>webdev</category>
      <category>architecture</category>
    </item>
    <item>
      <title>No Code E-commerce APP Builder | BuildEcom</title>
      <dc:creator>K B Zaman</dc:creator>
      <pubDate>Wed, 03 Sep 2025 06:25:37 +0000</pubDate>
      <link>https://dev.to/kbzaman2/no-code-e-commerce-app-builder-buildecom-3il6</link>
      <guid>https://dev.to/kbzaman2/no-code-e-commerce-app-builder-buildecom-3il6</guid>
      <description>&lt;h2&gt;
  
  
  Why mobile‑first matters for eCommerce
&lt;/h2&gt;

&lt;p&gt;Today’s shoppers live on their phones. &lt;strong&gt;Mobile commerce&lt;/strong&gt; is expected to account for more than half of all online sales worldwide and customers expect fast, app‑like experiences. Building a native mobile app from scratch usually requires &lt;strong&gt;thousands of dollars&lt;/strong&gt; and a &lt;strong&gt;team of developers&lt;/strong&gt;. That’s where no‑code platforms such as &lt;a href="https://buildecom.app/" rel="noopener noreferrer"&gt;BuildEcom&lt;/a&gt; come in.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is BuildEcom?
&lt;/h2&gt;

&lt;p&gt;According to &lt;a href="//producthunt.com/products/buildecom#:~:text=Visit%20website"&gt;Product&amp;nbsp;Hunt&lt;/a&gt;, BuildEcom “lets you turn your online store into a mobile app in minutes” and helps merchants manage products, boost sales and reach more customers without touching code.&lt;/p&gt;

&lt;p&gt;It works as a bridge between your WordPress WooCommerce shop and the BuildEcom mobile app infrastructure. By installing the official &lt;a href="https://wordpress.org/plugins/buildecom/#:~:text=Description" rel="noopener noreferrer"&gt;WordPress plugin&lt;/a&gt; you can connect your store, enable push notifications through Firebase and provide mobile‑ready APIs&lt;/p&gt;

&lt;h2&gt;
  
  
  Drag‑and‑drop app builder
&lt;/h2&gt;

&lt;p&gt;Inside the BuildEcom platform you design your mobile app using a visual editor—no coding required. SourceForge notes that BuildEcom “is a no‑code app builder designed for WooCommerce stores” that lets you manage products, track orders and send push notifications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Manage customers with notifications
&lt;/h2&gt;

&lt;p&gt;Push notifications are vital for re‑engaging mobile shoppers. BuildEcom uses Firebase Cloud Messaging to deliver order updates, promotions and abandoned‑cart reminders directly to the user’s device&lt;br&gt;
wordpress.org. Store owners can create custom notification templates from within WordPress and trigger them from WooCommerce events such as new orders or status changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Mobile commerce is no longer optional—it’s the default for many shoppers. BuildEcom makes it possible for WooCommerce merchants to join the mobile revolution without hiring developers or learning to code. By connecting your store through the BuildEcom plugin, customizing your app with a drag‑and‑drop builder and leveraging push notifications to drive engagement, you can launch a polished mobile app in days rather than months.&lt;/p&gt;

&lt;p&gt;If you’re ready to take your WooCommerce store to the next level, consider giving BuildEcom a try. With affordable pricing, cross‑platform support and a focus on usability, it could be the tool that helps you reach customers where they spend most of their time: on their phones.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Laravel Macroable Trait</title>
      <dc:creator>K B Zaman</dc:creator>
      <pubDate>Fri, 05 Nov 2021 17:08:29 +0000</pubDate>
      <link>https://dev.to/kbzaman2/laravel-macroable-trait-85i</link>
      <guid>https://dev.to/kbzaman2/laravel-macroable-trait-85i</guid>
      <description>&lt;p&gt;Laravel is very popular with developers for its beautiful features. Macroable trait is one of its many beautiful features.&lt;/p&gt;

&lt;h3&gt;
  
  
  Definition in my language:
&lt;/h3&gt;

&lt;p&gt;Speaking of this trait, I would like to say that it is a virtual method maker of class. That means there is a class in your project where you want to call some methods dynamically, but those methods do not have any physical presence in that class. In that case, you can get help from Macroable Trait.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to use:
&lt;/h3&gt;

&lt;p&gt;The first requirement to use this is to use the macroable trait in the class in which you want to create the macro. Then in the boot method of AppServiceProvider class, you have to write the code to create a macro of your class. A format of code is written below:&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="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="nc"&gt;YourClass&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;macro&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'methodName'&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="nv"&gt;$arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;// Your method body and your code&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;Suppose you think Laravel's Str class should have a method to connect two strings. But there is no such method in this class. Then you can create your own method for this class, without making any changes anywhere in this class. Because Laravel has some classes that use the Macroable trait by default. Among them Str class one. I will give the list of classes below. So how do we create a method in Str class to concat? You have already seen a demo format. That is the format we will use now.&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="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="nc"&gt;Str&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;macro&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'concat'&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="nv"&gt;$str1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$str2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kt"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$str1&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$str2&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;Now if you write &lt;code&gt;$str = Str::concat('My String 1', 'My String 2');&lt;/code&gt;  then you will see that the two strings are connected. This means that a virtual method has been created in this class without any change in the Str class.&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works:
&lt;/h3&gt;

&lt;p&gt;When you call the macro method in a class Macroable, it enters the static macro method of the Macroable Trait. I mentioned the method below:&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="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;macro&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$macro&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;macros&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$macros&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;It registers custom macros and stores them in its static macro property. Here comes the name of the custom method in the name variable and the instance of Closure in the macro variable.&lt;br&gt;
And when you call the custom method, the &lt;code&gt;__call()&lt;/code&gt; and &lt;code&gt;__callStatic()&lt;/code&gt; magic methods of Macroable Trait handle it dynamically.&lt;br&gt;
There is one more feature called mixin in Macroable Trait. I will try to talk about it in a later post InshaAllah.&lt;/p&gt;

</description>
      <category>php</category>
      <category>laravel</category>
      <category>trait</category>
      <category>webdevs</category>
    </item>
  </channel>
</rss>
