<?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: Codegenie</title>
    <description>The latest articles on DEV Community by Codegenie (@codegenie_be).</description>
    <link>https://dev.to/codegenie_be</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%2F3339251%2Fb19846c4-460c-439d-b7bb-9dfe07fc4d3e.png</url>
      <title>DEV Community: Codegenie</title>
      <link>https://dev.to/codegenie_be</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/codegenie_be"/>
    <language>en</language>
    <item>
      <title>Laravel env() Outside config/: Catch Deployment Bugs Before config:cache</title>
      <dc:creator>Codegenie</dc:creator>
      <pubDate>Thu, 20 Aug 2026 11:45:01 +0000</pubDate>
      <link>https://dev.to/codegenie_be/laravel-env-outside-config-catch-deployment-bugs-before-configcache-d83</link>
      <guid>https://dev.to/codegenie_be/laravel-env-outside-config-catch-deployment-bugs-before-configcache-d83</guid>
      <description>&lt;h2&gt;
  
  
  The bug only appears after configuration caching
&lt;/h2&gt;

&lt;p&gt;A Laravel application can behave perfectly during development and then fail after deployment because a service class reads an environment variable directly:&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="c1"&gt;// app/Services/AcmeClient.php&lt;/span&gt;
&lt;span class="nv"&gt;$token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ACME_TOKEN'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Laravel's configuration cache changes the boot process. Once configuration has been cached, the framework does not load the application's &lt;code&gt;.env&lt;/code&gt; file for normal requests or Artisan commands. A direct &lt;code&gt;env()&lt;/code&gt; call outside a configuration file may therefore return only an externally supplied system value or its fallback.&lt;/p&gt;

&lt;p&gt;The reliable pattern is to read the environment variable once from a configuration file:&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="c1"&gt;// config/services.php&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'acme'&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;'token'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ACME_TOKEN'&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;Application code should then use Laravel's configuration repository:&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="c1"&gt;// app/Services/AcmeClient.php&lt;/span&gt;
&lt;span class="nv"&gt;$token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'services.acme.token'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the primary fix. A package should never be used to justify keeping unsafe environment access in application code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Environment drift is a separate problem
&lt;/h2&gt;

&lt;p&gt;Even when every &lt;code&gt;env()&lt;/code&gt; call is in the right place, teams still have to keep several environment contracts aligned. A project might contain &lt;code&gt;.env&lt;/code&gt;, &lt;code&gt;.env.testing&lt;/code&gt;, &lt;code&gt;.env.production&lt;/code&gt;, &lt;code&gt;.env.sample&lt;/code&gt;, or a template with a company-specific name.&lt;/p&gt;

&lt;p&gt;Consider these files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# .env
APP_NAME=Codegenie
ACME_TOKEN=local-secret
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# .env.production
APP_NAME=Codegenie
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The values are expected to differ, but the missing &lt;code&gt;ACME_TOKEN&lt;/code&gt; key can still indicate an incomplete deployment contract. Other easy-to-miss cases include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a duplicate active assignment in one file;&lt;/li&gt;
&lt;li&gt;keys that differ only by case;&lt;/li&gt;
&lt;li&gt;a key used by the application but declared nowhere;&lt;/li&gt;
&lt;li&gt;an obsolete key that might no longer be consumed;&lt;/li&gt;
&lt;li&gt;direct &lt;code&gt;getenv()&lt;/code&gt;, &lt;code&gt;$_ENV&lt;/code&gt;, or &lt;code&gt;$_SERVER&lt;/code&gt; access;&lt;/li&gt;
&lt;li&gt;a dynamic lookup such as &lt;code&gt;env('SERVICE_'.$driver)&lt;/code&gt; that static analysis cannot resolve safely;&lt;/li&gt;
&lt;li&gt;a Vite key referenced in frontend code but absent from the environment contract.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A useful manual review
&lt;/h2&gt;

&lt;p&gt;Before adding tooling, a team can already reduce these failures with a small review:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Search application-owned PHP files for &lt;code&gt;env(&lt;/code&gt; and move valid reads into &lt;code&gt;config/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Compare the key inventories of the environment files that represent complete environments.&lt;/li&gt;
&lt;li&gt;Treat commented assignments in non-active templates as documentation, not active values.&lt;/li&gt;
&lt;li&gt;Check &lt;code&gt;phpunit.xml&lt;/code&gt; and &lt;code&gt;.env.testing&lt;/code&gt; together.&lt;/li&gt;
&lt;li&gt;Review Vite &lt;code&gt;import.meta.env&lt;/code&gt; and &lt;code&gt;loadEnv()&lt;/code&gt; usage.&lt;/li&gt;
&lt;li&gt;Run the application with configuration cached before deployment.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Do not compare or print secret values while performing this review. Environment URLs, credentials, application keys, and tokens are supposed to differ between environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automating the development feedback loop
&lt;/h2&gt;

&lt;p&gt;I maintain &lt;a href="https://github.com/Codegenie-BE/laravel-env-guard" rel="noopener noreferrer"&gt;Laravel Env Guard&lt;/a&gt; through Codegenie to automate this review for current Laravel applications.&lt;/p&gt;

&lt;p&gt;Install it as a development dependency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require &lt;span class="nt"&gt;--dev&lt;/span&gt; codegenie-be/laravel-env-guard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Laravel package discovery registers the guard automatically. By default it runs only during console boots in the &lt;code&gt;local&lt;/code&gt; environment. It does not require a separate audit command or a specially named &lt;code&gt;.env.example&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Each guarded audit reads the current project files directly and checks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;unsafe &lt;code&gt;env()&lt;/code&gt; and &lt;code&gt;Illuminate\Support\Env::get()&lt;/code&gt; calls outside &lt;code&gt;config/&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;direct raw environment access for project-owned keys;&lt;/li&gt;
&lt;li&gt;duplicate, case-mismatched, missing, and possibly unused keys;&lt;/li&gt;
&lt;li&gt;drift across automatically discovered plaintext &lt;code&gt;.env&lt;/code&gt; and &lt;code&gt;.env.*&lt;/code&gt; files;&lt;/li&gt;
&lt;li&gt;explicit reference or comparison files when a project configures them;&lt;/li&gt;
&lt;li&gt;PHPUnit, Vite, Blade, Docker, workflow, and other application-owned usage covered by the scanner.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Blocking findings fail fast by default. Warnings and errors are written to STDERR as a compact key-only report during Artisan commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  Secret handling is a hard boundary
&lt;/h2&gt;

&lt;p&gt;The guard compares keys, never values. Its reports, exceptions, and logs do not include environment values. It performs no telemetry or network requests, never modifies &lt;code&gt;.env&lt;/code&gt; files, and does not synchronize secrets.&lt;/p&gt;

&lt;p&gt;Encrypted environment files are intentionally excluded because auditing them would require decryption. Production and normal HTTP scanning are disabled by default. The package is a development guard, not a secret manager or deployment system.&lt;/p&gt;

&lt;p&gt;Likely-unused diagnostics also require judgment: a key may be consumed by infrastructure, a package, Docker, a process manager, or code outside the configured scan paths. Projects can explicitly ignore legitimate external keys and patterns.&lt;/p&gt;

&lt;h2&gt;
  
  
  A gradual rollout works best
&lt;/h2&gt;

&lt;p&gt;For an existing application, I recommend this order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install the package on a branch.&lt;/li&gt;
&lt;li&gt;Fix direct &lt;code&gt;env()&lt;/code&gt; usage outside &lt;code&gt;config/&lt;/code&gt; first.&lt;/li&gt;
&lt;li&gt;Review duplicate and case-mismatch errors.&lt;/li&gt;
&lt;li&gt;Decide which environment files are complete peers and which are partial Vite-style layers.&lt;/li&gt;
&lt;li&gt;Suppress only intentional external or infrastructure-owned cases.&lt;/li&gt;
&lt;li&gt;Verify the result with &lt;code&gt;config:cache&lt;/code&gt; and the normal test suite.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The current release, &lt;a href="https://github.com/Codegenie-BE/laravel-env-guard/releases/tag/v1.2.1" rel="noopener noreferrer"&gt;v1.2.1&lt;/a&gt;, supports Laravel 12 and 13 across their valid PHP 8.2–8.5 combinations. The package is also available on &lt;a href="https://packagist.org/packages/codegenie-be/laravel-env-guard" rel="noopener noreferrer"&gt;Packagist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Disclosure: I maintain this open-source package through Codegenie. I am especially interested in technical feedback about renamed environment templates, partial environment layers, framework keys, and false-positive or false-negative edge cases. Please do not include real environment values or secrets in reports.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>opensource</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Laravel .env changes not reflected after deployment: causes and a safe shared-hosting fallback</title>
      <dc:creator>Codegenie</dc:creator>
      <pubDate>Tue, 11 Aug 2026 19:28:32 +0000</pubDate>
      <link>https://dev.to/codegenie_be/laravel-env-changes-not-reflected-after-deployment-causes-and-a-safe-shared-hosting-fallback-5ec0</link>
      <guid>https://dev.to/codegenie_be/laravel-env-changes-not-reflected-after-deployment-causes-and-a-safe-shared-hosting-fallback-5ec0</guid>
      <description>&lt;p&gt;Changing a production &lt;code&gt;.env&lt;/code&gt; file and still seeing the old database host, mail settings, application URL, or feature flag is a familiar Laravel deployment surprise.&lt;/p&gt;

&lt;p&gt;Usually, Laravel is doing exactly what it was told to do: use a cached configuration snapshot.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Disclosure: Codegenie maintains the open-source package discussed near the end of this article. The normal Laravel deployment commands remain the preferred solution.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why the new value is ignored
&lt;/h2&gt;

&lt;p&gt;Laravel's configuration files read environment variables and expose them through the configuration repository:&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="c1"&gt;// config/services.php&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'example'&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;'endpoint'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'EXAMPLE_ENDPOINT'&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;Application code should then read the configuration value:&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="nv"&gt;$endpoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'services.example.endpoint'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you run:&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 config:cache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Laravel combines the configuration into a cached snapshot. Once that snapshot exists, the framework does not load the application's &lt;code&gt;.env&lt;/code&gt; file during requests or Artisan commands. That is why editing &lt;code&gt;.env&lt;/code&gt; alone does not change the value your application sees.&lt;/p&gt;

&lt;p&gt;Laravel also recommends calling &lt;code&gt;env()&lt;/code&gt; only from configuration files. Calling &lt;code&gt;env()&lt;/code&gt; directly from controllers, jobs, or services can return &lt;code&gt;null&lt;/code&gt; after configuration has been cached.&lt;/p&gt;

&lt;p&gt;The official explanation is in Laravel's &lt;a href="https://laravel.com/docs/13.x/configuration#configuration-caching" rel="noopener noreferrer"&gt;configuration caching documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The normal production fix
&lt;/h2&gt;

&lt;p&gt;A reliable deployment should rebuild the cache after the new code and environment configuration are in place:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--no-dev&lt;/span&gt; &lt;span class="nt"&gt;--optimize-autoloader&lt;/span&gt;
php artisan config:cache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the application uses route caching, rebuild that too:&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 route:cache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you intentionally do not want cached configuration, clear it instead:&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 config:clear
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part is that the cache command belongs to the deployment process. Run it on every release, after all relevant files and environment settings have been updated.&lt;/p&gt;

&lt;p&gt;For deployments with release directories, build caches inside the new release before switching the live symlink. That avoids serving a half-updated application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why FTP and shared hosting make this harder
&lt;/h2&gt;

&lt;p&gt;The ideal flow assumes you can execute PHP CLI commands during deployment.&lt;/p&gt;

&lt;p&gt;On shared hosting that assumption may be false:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the site is uploaded through FTP;&lt;/li&gt;
&lt;li&gt;cPanel or Plesk provides no useful deploy hook;&lt;/li&gt;
&lt;li&gt;SSH is unavailable;&lt;/li&gt;
&lt;li&gt;PHP functions such as &lt;code&gt;exec()&lt;/code&gt; are disabled;&lt;/li&gt;
&lt;li&gt;the old cache file survives while &lt;code&gt;.env&lt;/code&gt; or &lt;code&gt;config/*.php&lt;/code&gt; changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Clearing a browser cache or application data cache does not solve this. Configuration cache and route cache are deployment artifacts, not regular response or database cache.&lt;/p&gt;

&lt;p&gt;A web request could notice the problem, but timing matters. Laravel reads cached configuration while the application is bootstrapping. Middleware and normal service providers run too late to prevent that request from loading stale configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a safe fallback needs to do
&lt;/h2&gt;

&lt;p&gt;A useful fallback should protect correctness without pretending to replace a deployment pipeline.&lt;/p&gt;

&lt;p&gt;It should:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;run before Laravel consumes cached configuration or routes;&lt;/li&gt;
&lt;li&gt;detect relevant source changes without reading or storing secret values;&lt;/li&gt;
&lt;li&gt;stop stale cache from being used immediately;&lt;/li&gt;
&lt;li&gt;rebuild through PHP CLI when that is available;&lt;/li&gt;
&lt;li&gt;degrade safely when shell execution is unavailable;&lt;/li&gt;
&lt;li&gt;use locks and exact source signatures to avoid racing repairs;&lt;/li&gt;
&lt;li&gt;avoid enabling cache types the application was not already using.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That design is the basis of &lt;a href="https://codegenie-be.github.io/laravel-config-cache-guard/" rel="noopener noreferrer"&gt;Laravel Config Cache Guard&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the fallback works
&lt;/h2&gt;

&lt;p&gt;Install it with one Composer command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require codegenie-be/laravel-config-cache-guard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Composer loads the guard before &lt;code&gt;bootstrap/app.php&lt;/code&gt;. It compares metadata for relevant sources such as &lt;code&gt;.env&lt;/code&gt;, configuration files, route files, and route bootstrap files. It tracks timestamps, sizes, and filesystem metadata—not environment values.&lt;/p&gt;

&lt;p&gt;When the sources are unchanged, the request continues normally.&lt;/p&gt;

&lt;p&gt;When an existing config cache is stale, the guard prevents Laravel from using it. When an existing route cache is stale, the guard bypasses it using a signature-based cache path.&lt;/p&gt;

&lt;p&gt;If PHP CLI execution is available, it can rebuild before Laravel boots.&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;exec()&lt;/code&gt; is disabled, the current request continues without the known-stale deployment cache. The guard writes an internal pending marker, and the package service provider rebuilds through Laravel's own &lt;code&gt;Artisan::call()&lt;/code&gt; after the response. A following request can then use the refreshed cache.&lt;/p&gt;

&lt;p&gt;There is no public repair endpoint, no repair token, and no telemetry.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defaults that avoid surprising applications
&lt;/h2&gt;

&lt;p&gt;The package does &lt;strong&gt;not&lt;/strong&gt; automatically turn on config caching for every project.&lt;/p&gt;

&lt;p&gt;If no config cache exists, config-cache creation remains disabled unless you explicitly opt in:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Route guarding starts only when the application already has route cache.&lt;/p&gt;

&lt;p&gt;This matters because a correctness guard should not silently change an application's caching policy.&lt;/p&gt;

&lt;p&gt;You can optionally inspect the integration with:&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 config-cache-guard:status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That status command is verification, not a second installation step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;This fallback still needs a writable Laravel bootstrap cache directory.&lt;/p&gt;

&lt;p&gt;Without &lt;code&gt;exec()&lt;/code&gt;, repair happens after the current response. The first request runs without stale deployment cache, but it may be uncached. The next request uses the rebuilt cache if repair succeeded.&lt;/p&gt;

&lt;p&gt;Custom bootstrap paths selected later in application code cannot always be discovered before Laravel boots.&lt;/p&gt;

&lt;p&gt;And most importantly: if your platform supports reliable deployment hooks, keep using the standard Laravel cache commands. The package is a safety net for restricted hosting, not a replacement for a healthy deployment process and not a promise to make every website faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compatibility and testing
&lt;/h2&gt;

&lt;p&gt;The current release supports Laravel 12 and 13 on non-EOL PHP versions. Its test suite installs fresh Laravel applications and verifies real HTTP requests, including Linux and Windows scenarios and the &lt;code&gt;exec()&lt;/code&gt;-disabled repair path.&lt;/p&gt;

&lt;p&gt;The source, demo, security notes, and deployment recipes are available on &lt;a href="https://github.com/Codegenie-BE/laravel-config-cache-guard" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you deploy Laravel through FTP, cPanel, Plesk, or another restricted host, technical feedback is especially welcome. Which deployment limitations have you encountered, and how do you currently prevent stale configuration from reaching users?&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>devops</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Laravel Livewire Multi-Step Forms: Validation and Safe Submission</title>
      <dc:creator>Codegenie</dc:creator>
      <pubDate>Wed, 09 Jul 2025 14:40:30 +0000</pubDate>
      <link>https://dev.to/codegenie_be/i-built-an-open-source-multi-step-form-wizard-for-livewire-3-heres-why-and-how-you-can-use-it-n01</link>
      <guid>https://dev.to/codegenie_be/i-built-an-open-source-multi-step-form-wizard-for-livewire-3-heres-why-and-how-you-can-use-it-n01</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Updated for the stable v1.0.0 package release (August 2026).&lt;/strong&gt; The original project has been refactored from a demo application into an installable Composer package for Laravel 12–13 and Livewire 3–4.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Long forms are easier to complete when they are split into focused steps, but the server-side contract still matters: users must not be able to skip validation, submit before the review step, or inject values outside configured choices.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;Laravel Livewire Multi-Step Form&lt;/strong&gt; as a small, configuration-driven package that handles that reusable flow while leaving persistence, authorization, mail, redirects, and rate limiting in your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require codegenie-be/laravel-livewire-multistep-form
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PHP 8.2 through supported PHP 8.x releases&lt;/li&gt;
&lt;li&gt;Laravel 12 or 13&lt;/li&gt;
&lt;li&gt;Livewire 3.6+ or 4.x&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Laravel package discovery registers the component automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Define fields, not a second application
&lt;/h2&gt;

&lt;p&gt;Pass a field configuration to the registered Livewire component:&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;livewire:codegenie-multistep-form
    :fields="[
        'name' =&amp;gt; [
            'rules' =&amp;gt; 'required|string|min:2|max:120',
            'label' =&amp;gt; 'Name',
            'step' =&amp;gt; 1,
            'type' =&amp;gt; 'text',
        ],
        'email' =&amp;gt; [
            'rules' =&amp;gt; 'required|email|max:255',
            'label' =&amp;gt; 'Email address',
            'step' =&amp;gt; 2,
            'type' =&amp;gt; 'email',
        ],
        'topic' =&amp;gt; [
            'rules' =&amp;gt; 'required|string',
            'label' =&amp;gt; 'Topic',
            'step' =&amp;gt; 2,
            'type' =&amp;gt; 'select',
            'options' =&amp;gt; [
                'general' =&amp;gt; 'General question',
                'support' =&amp;gt; 'Support',
            ],
        ],
        'message' =&amp;gt; [
            'rules' =&amp;gt; 'required|string|min:10|max:5000',
            'label' =&amp;gt; 'Message',
            'step' =&amp;gt; 3,
            'type' =&amp;gt; 'textarea',
        ],
    ]"
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Steps start at 1 and remain consecutive. The package currently supports text-like inputs, textarea, and select fields. File uploads, repeaters, nested names, checkboxes, and radio groups are intentionally outside v1.0.0.&lt;/p&gt;

&lt;h2&gt;
  
  
  Validation is enforced on the server
&lt;/h2&gt;

&lt;p&gt;Each Next action validates only the current step. Final submission is accepted only from the generated review step, then validates the complete form again.&lt;/p&gt;

&lt;p&gt;Select option keys form a server-side allow-list. If final validation fails, the wizard returns to the first invalid step and requests focus for that field.&lt;/p&gt;

&lt;p&gt;For Laravel rule objects, closures, or application-sensitive validation details, extend the component and keep those rules out of public Livewire state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Codegenie\LivewireMultistepForm\Livewire\MultiStepForm&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\Validation\Rule&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;ContactWizard&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;MultiStepForm&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;serverValidationRules&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'email'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;Rule&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'users'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'email'&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;h2&gt;
  
  
  Your application owns the submission
&lt;/h2&gt;

&lt;p&gt;The base component deliberately does not write to a database or send mail. Extend it when you need server-side persistence:&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;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;handleSubmission&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;ContactRequest&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&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;Only configured, validated fields reach this hook. Authorization, rate limiting, retention, redirects, and other application concerns remain yours.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accessibility, localization, and styling
&lt;/h2&gt;

&lt;p&gt;The default view includes semantic form and fieldset markup, associated labels and errors, progressbar metadata, visible focus states, focus management, reduced-motion handling, and instance-scoped IDs.&lt;/p&gt;

&lt;p&gt;English, Dutch, and French interface translations ship with the package. The Blade view and translations can be published when an application needs custom copy or markup.&lt;/p&gt;

&lt;p&gt;The view uses Tailwind utility classes but ships no compiled frontend assets. Tailwind 3 projects add the vendor view path to &lt;code&gt;content&lt;/code&gt;; Tailwind 4 projects add it with &lt;code&gt;@source&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try or inspect it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://laravel-livewire.codegenie.be" rel="noopener noreferrer"&gt;Live demo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Codegenie-BE/laravel-livewire-multistep-form" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://packagist.org/packages/codegenie-be/laravel-livewire-multistep-form" rel="noopener noreferrer"&gt;Packagist&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Codegenie-BE/laravel-livewire-multistep-form/releases/tag/v1.0.0" rel="noopener noreferrer"&gt;v1.0.0 release notes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The package is MIT licensed. Compatibility is tested across Laravel 12–13, Livewire 3–4, and applicable PHP 8.2–8.5 combinations, including minimum dependency sets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclosure:&lt;/strong&gt; I maintain this open-source package through Codegenie. Feedback on validation edge cases, accessibility, and real-world Livewire 4 usage is especially welcome.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>livewire</category>
      <category>opensource</category>
      <category>tailwindcss</category>
    </item>
  </channel>
</rss>
