<?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: Faizan</title>
    <description>The latest articles on DEV Community by Faizan (@faizan050).</description>
    <link>https://dev.to/faizan050</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%2F4190132%2F01e43b5e-bc83-43c4-892b-d1c0a41da0a5.jpg</url>
      <title>DEV Community: Faizan</title>
      <link>https://dev.to/faizan050</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/faizan050"/>
    <language>en</language>
    <item>
      <title>Unknown character set index for field received from server</title>
      <dc:creator>Faizan</dc:creator>
      <pubDate>Sun, 18 Oct 2026 11:52:56 +0000</pubDate>
      <link>https://dev.to/faizan050/unknown-character-set-index-for-field-received-from-server-4nc3</link>
      <guid>https://dev.to/faizan050/unknown-character-set-index-for-field-received-from-server-4nc3</guid>
      <description>&lt;p&gt;&lt;code&gt;java.sql.SQLException: Unknown character set index for field '255' received from server.&lt;/code&gt; If your app suddenly throws this after moving to MySQL 8, the database isn't broken. Your client is too old to understand the collation the server is sending back.&lt;/p&gt;

&lt;p&gt;The "unknown character set index for field received from server" error means MySQL sent a collation ID (usually 255, which is &lt;code&gt;utf8mb4_0900_ai_ci&lt;/code&gt;) that your driver doesn't know about. Fix it by upgrading the MySQL driver. If you can't, switch the server and your tables to &lt;code&gt;utf8mb4_unicode_ci&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why unknown character set index for field received from server happens
&lt;/h2&gt;

&lt;p&gt;Every column in a result set comes with metadata, including a numeric collation ID. MySQL 8.0 made &lt;code&gt;utf8mb4_0900_ai_ci&lt;/code&gt; the default collation for &lt;code&gt;utf8mb4&lt;/code&gt;, and its ID is 255.&lt;/p&gt;

&lt;p&gt;Older drivers carry a hardcoded lookup table of collation IDs. That table ends before 255. So when the driver reads the field metadata, it finds an ID it has never seen and gives up.&lt;/p&gt;

&lt;p&gt;You'll typically hit it in these situations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An old Java app using a legacy &lt;code&gt;mysql-connector-java&lt;/code&gt; 5.1.x jar, pointed at a fresh MySQL 8 server&lt;/li&gt;
&lt;li&gt;A PHP 7.x build from before mysqlnd learned about the new collations&lt;/li&gt;
&lt;li&gt;A Docker setup where you bumped the image from &lt;code&gt;mysql:5.7&lt;/code&gt; to &lt;code&gt;mysql:8&lt;/code&gt; and changed nothing else&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To reproduce it, take any old client, connect to a default MySQL 8 install, and run &lt;code&gt;SELECT&lt;/code&gt; on a table created with default settings. It fails on the first string column.&lt;/p&gt;

&lt;h2&gt;
  
  
  Error variations you might see instead
&lt;/h2&gt;

&lt;p&gt;The same root cause shows up with different wording depending on the client:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Connector/J, at connect time:&lt;/strong&gt; &lt;code&gt;Unknown initial character set index '255' received from server. Initial client character set can be forced via the 'characterEncoding' property.&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connector/J, at query time:&lt;/strong&gt; &lt;code&gt;Unknown character set index for field '255' received from server.&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PHP mysqlnd:&lt;/strong&gt; &lt;code&gt;Server sent charset (255) unknown to the client. Please, report to the developers&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Occasionally the number is something else, like 224 or 246, on very old drivers. The fix is the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Confirm the server is sending collation 255
&lt;/h2&gt;

&lt;p&gt;Log in with the &lt;code&gt;mysql&lt;/code&gt; CLI and check what the server defaults to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt; &lt;span class="n"&gt;VARIABLES&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'collation_%'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SHOW&lt;/span&gt; &lt;span class="n"&gt;VARIABLES&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'character_set_server'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;collation_server&lt;/code&gt; or &lt;code&gt;collation_database&lt;/code&gt; shows &lt;code&gt;utf8mb4_0900_ai_ci&lt;/code&gt;, you've found the source. You can confirm the ID mapping directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;COLLATION_NAME&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;information_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;COLLATIONS&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Upgrade the MySQL driver (the real fix)
&lt;/h2&gt;

&lt;p&gt;This is the fix I'd go for first. Changing collations is a workaround; a current driver simply understands ID 255.&lt;/p&gt;

&lt;p&gt;For Java with Maven, replace the old &lt;code&gt;mysql:mysql-connector-java&lt;/code&gt; artifact with the current one. If you're on Spring Boot, leave the version out and let Boot manage it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.mysql&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;mysql-connector-j&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;runtime&lt;span class="nt"&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Gradle equivalent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;runtimeOnly&lt;/span&gt; &lt;span class="s1"&gt;'com.mysql:mysql-connector-j'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not on Spring Boot? Pick the latest version from Maven Central and pin it. Also update the driver class if your config still says &lt;code&gt;com.mysql.jdbc.Driver&lt;/code&gt;; the current one is &lt;code&gt;com.mysql.cj.jdbc.Driver&lt;/code&gt;. If Spring then complains about the datasource, see this fix for &lt;a href="https://headsntail.com/blog/beancreationexception-database-type-none-mysql-fix" rel="noopener noreferrer"&gt;BeanCreationException with database type NONE on MySQL&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For PHP, check your version and mysqlnd build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php &lt;span class="nt"&gt;-v&lt;/span&gt;
php &lt;span class="nt"&gt;-i&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; mysqlnd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On Windows (XAMPP), use &lt;code&gt;php -i | findstr mysqlnd&lt;/code&gt;. If you're on an old PHP 7.x release, upgrading PHP is the clean fix. Current PHP versions handle MySQL 8 collations without any extra config.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: If you can't upgrade, change the server default collation
&lt;/h2&gt;

&lt;p&gt;Sometimes the client is a vendor app or a legacy service you can't touch. In that case, make the server stop sending 255.&lt;/p&gt;

&lt;p&gt;Edit &lt;code&gt;my.cnf&lt;/code&gt; (often &lt;code&gt;/etc/mysql/my.cnf&lt;/code&gt; or &lt;code&gt;/etc/mysql/mysql.conf.d/mysqld.cnf&lt;/code&gt; on Linux, &lt;code&gt;my.ini&lt;/code&gt; on Windows):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[mysqld]&lt;/span&gt;
&lt;span class="py"&gt;character-set-server&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;utf8mb4&lt;/span&gt;
&lt;span class="py"&gt;collation-server&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;utf8mb4_unicode_ci&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart MySQL:&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="nb"&gt;sudo &lt;/span&gt;systemctl restart mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Docker Compose, pass the flags on the command line instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql:8&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;--character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Gotcha:&lt;/strong&gt; this only changes defaults for new objects. Tables you already created keep &lt;code&gt;utf8mb4_0900_ai_ci&lt;/code&gt;, and their columns can still report 255. That's why most people who "fixed the config" still see the error. Do Step 4.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Convert existing tables away from utf8mb4_0900_ai_ci
&lt;/h2&gt;

&lt;p&gt;Find the affected tables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;TABLE_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TABLE_COLLATION&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;information_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TABLES&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;TABLE_SCHEMA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'your_db'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;TABLE_COLLATION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'utf8mb4_0900_ai_ci'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change the database default, then generate the &lt;code&gt;ALTER&lt;/code&gt; statements instead of typing them by hand:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;your_db&lt;/span&gt; &lt;span class="nb"&gt;CHARACTER&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;utf8mb4&lt;/span&gt; &lt;span class="k"&gt;COLLATE&lt;/span&gt; &lt;span class="n"&gt;utf8mb4_unicode_ci&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;CONCAT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ALTER TABLE `'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;TABLE_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="s1"&gt;'` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;information_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TABLES&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;TABLE_SCHEMA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'your_db'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;TABLE_COLLATION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'utf8mb4_0900_ai_ci'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the output and run it. Back up first. &lt;code&gt;CONVERT TO&lt;/code&gt; rebuilds each table, which takes time and locks on large tables, so don't do it on production at noon. The two collations also compare some characters differently, so a unique index can occasionally throw a duplicate-key error during conversion. Test on a copy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Set the charset explicitly in your connection settings
&lt;/h2&gt;

&lt;p&gt;Pin the connection collation so the client and server agree from the first handshake.&lt;/p&gt;

&lt;p&gt;JDBC URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jdbc:mysql://localhost:3306/your_db?characterEncoding=UTF-8&amp;amp;connectionCollation=utf8mb4_unicode_ci
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Laravel, in &lt;code&gt;config/database.php&lt;/code&gt; under the &lt;code&gt;mysql&lt;/code&gt; connection:&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="s1"&gt;'charset'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'utf8mb4'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="s1"&gt;'collation'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'utf8mb4_unicode_ci'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Laravel already defaults to these, but check that nothing in &lt;code&gt;.env&lt;/code&gt; or a custom connection overrides them. If your connection parameters are confusing in plain PHP, this breakdown of &lt;a href="https://headsntail.com/blog/mysqli-connect-host-parameter-explained" rel="noopener noreferrer"&gt;the host parameter in mysqli_connect()&lt;/a&gt; covers the basics.&lt;/p&gt;

&lt;p&gt;One opinion: adding &lt;code&gt;characterEncoding=UTF-8&lt;/code&gt; alone to an old driver is a weak fix. It can get you past the "initial" variant at connect time, but the "for field" variant comes from table metadata, so it often comes straight back on the first query.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Verify the fix
&lt;/h2&gt;

&lt;p&gt;Check that no columns still use the 0900 collation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;TABLE_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;COLUMN_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;COLLATION_NAME&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;information_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;COLUMNS&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;TABLE_SCHEMA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'your_db'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="k"&gt;COLLATION_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'utf8mb4_0900_ai_ci'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You want &lt;code&gt;Empty set&lt;/code&gt;. Then restart your app and run the query that failed before. If you're on Laravel, a quick &lt;code&gt;php artisan migrate:status&lt;/code&gt; hits the database and is a fast smoke test. If seeding breaks after the collation change, this guide on &lt;a href="https://headsntail.com/blog/laravel-migrate-fresh-seed-table-not-seeding-mysql" rel="noopener noreferrer"&gt;migrate:fresh --seed not seeding into MySQL&lt;/a&gt; may help.&lt;/p&gt;

&lt;p&gt;For future migrations, keep the collation consistent so new tables don't drift back to the server default. If you'd rather have someone check your setup directly, you can &lt;a href="https://headsntail.com/contact" rel="noopener noreferrer"&gt;contact HeadsNTail&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is character set index 255 in MySQL?
&lt;/h3&gt;

&lt;p&gt;It's the numeric ID of the &lt;code&gt;utf8mb4_0900_ai_ci&lt;/code&gt; collation, the default for &lt;code&gt;utf8mb4&lt;/code&gt; in MySQL 8.0. Drivers written before MySQL 8 don't have it in their lookup table, which is why they reject it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why did this error start after upgrading to MySQL 8?
&lt;/h3&gt;

&lt;p&gt;MySQL 5.7 defaulted to collations your old driver already knew. MySQL 8 changed the default to &lt;code&gt;utf8mb4_0900_ai_ci&lt;/code&gt;, so any table created on the new server, or imported without an explicit collation, now sends ID 255 to the client.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is utf8mb4_unicode_ci worse than utf8mb4_0900_ai_ci?
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;utf8mb4_0900_ai_ci&lt;/code&gt; follows a newer Unicode collation standard, so sorting and comparison can be more accurate for some languages. For most English or mixed-language web apps, &lt;code&gt;utf8mb4_unicode_ci&lt;/code&gt; works fine. Still, upgrading the driver and keeping the MySQL 8 default is the better long-term choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does adding characterEncoding=UTF-8 to the JDBC URL fix it?
&lt;/h3&gt;

&lt;p&gt;Sometimes, for the "Unknown initial character set index" variant raised at connect time. It usually doesn't fix the "for field" variant, because that ID comes from the column metadata. Upgrade the connector or convert the tables.&lt;/p&gt;

&lt;p&gt;If you see "unknown character set index for field received from server" again later, check whether a new table was created with the server default, then rerun the Step 6 query to find it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://headsntail.com/blog/mysql-unknown-character-set-index-for-field-255" rel="noopener noreferrer"&gt;headsntail.com&lt;/a&gt;. Free tools for PHP, Laravel and cPanel work: &lt;a href="https://headsntail.com/tools" rel="noopener noreferrer"&gt;headsntail.com/tools&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>mysql</category>
      <category>database</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Cloudflare JS Challenge Is Breaking My SPA: Laravel Fix</title>
      <dc:creator>Faizan</dc:creator>
      <pubDate>Sun, 18 Oct 2026 11:41:23 +0000</pubDate>
      <link>https://dev.to/faizan050/cloudflare-js-challenge-is-breaking-my-spa-laravel-fix-2416</link>
      <guid>https://dev.to/faizan050/cloudflare-js-challenge-is-breaking-my-spa-laravel-fix-2416</guid>
      <description>&lt;p&gt;By the end of this, your Laravel SPA will handle Cloudflare challenges instead of crashing on them, and the fix takes about 30 minutes. If your bug report says "a Cloudflare JS challenge is breaking my SPA", the problem isn't in your Vue or Laravel code.&lt;/p&gt;

&lt;p&gt;What changed is how Cloudflare describes and handles these challenges. Its docs now list the old JS Challenge as a &lt;strong&gt;Non-Interactive Challenge&lt;/strong&gt; and point SPA owners to &lt;strong&gt;Turnstile pre-clearance&lt;/strong&gt; for fetch and XHR calls. I couldn't confirm an exact date for either change, so go by the labels your dashboard shows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Short answer:&lt;/strong&gt; Cloudflare challenges are HTML pages that need a full browser navigation to run. When one lands on an axios or fetch call, your SPA gets a 403 with a &lt;code&gt;cf-mitigated: challenge&lt;/code&gt; header and HTML instead of JSON. Fix it by excluding API routes from challenge rules, reloading the page when that header appears, or using Turnstile pre-clearance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the Cloudflare JS challenge is breaking my SPA
&lt;/h2&gt;

&lt;p&gt;I'll use one example throughout. You have a Laravel + Vue storefront at &lt;code&gt;shop.example.com&lt;/code&gt;. The product list loads from &lt;code&gt;/api/products&lt;/code&gt; with axios, and you have a WAF custom rule that challenges traffic from outside your main market.&lt;/p&gt;

&lt;p&gt;Here's the sequence that breaks it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A visitor opens &lt;code&gt;shop.example.com&lt;/code&gt;. That's a normal page load, so the browser shows the challenge, passes it, and Cloudflare sets a &lt;code&gt;cf_clearance&lt;/code&gt; cookie.&lt;/li&gt;
&lt;li&gt;The SPA works. Every axios call sends the cookie and gets through.&lt;/li&gt;
&lt;li&gt;The cookie expires (its lifetime is the zone's &lt;strong&gt;Challenge Passage&lt;/strong&gt; setting), or a rule matches the API path more strictly than the page.&lt;/li&gt;
&lt;li&gt;The next call to &lt;code&gt;/api/products&lt;/code&gt; gets challenged. Cloudflare returns an HTML challenge page with a 403.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A browser can run a challenge page when it navigates to it. It can't run one that arrives as the body of an XHR or fetch response. Your JavaScript just receives a string of HTML it has no use for.&lt;/p&gt;

&lt;p&gt;That's also why it works fine on your machine. There's no Cloudflare in front of &lt;code&gt;php artisan serve&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means for PHP/web developers
&lt;/h2&gt;

&lt;p&gt;The first thing to accept: &lt;strong&gt;Laravel never sees these requests.&lt;/strong&gt; Cloudflare answers them at the edge. Nothing shows up in &lt;code&gt;storage/logs/laravel.log&lt;/code&gt;, and no middleware or exception handler can catch them. The fix lives in Cloudflare's settings or in your frontend.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reproduce the 403 cf-mitigated: challenge response
&lt;/h3&gt;

&lt;p&gt;You don't need to wait for a real visitor to hit it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In Cloudflare, add a temporary custom rule with action &lt;strong&gt;Managed Challenge&lt;/strong&gt; and this expression (use your own IP):
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(ip.src eq 203.0.113.10 and starts_with(http.request.uri.path, "/api/"))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Open the site, then delete the &lt;code&gt;cf_clearance&lt;/code&gt; cookie in DevTools (Application tab, Cookies).&lt;/li&gt;
&lt;li&gt;Trigger an API call and open the request in the Network tab.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You should see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP/2 403
content-type: text/html; charset=UTF-8
cf-mitigated: challenge
server: cloudflare
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;cf-mitigated: challenge&lt;/code&gt; is the header Cloudflare documents for detecting challenged responses in fetch and XHR calls. It's what your fix will check for.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why you see "Unexpected token '&amp;lt;'" instead of a challenge
&lt;/h3&gt;

&lt;p&gt;If you use &lt;code&gt;fetch()&lt;/code&gt; and call &lt;code&gt;response.json()&lt;/code&gt; without checking the status, the console shows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SyntaxError: Unexpected token '&amp;lt;', "&amp;lt;!DOCTYPE "... is not valid JSON
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With axios you usually get a rejected promise with &lt;code&gt;status: 403&lt;/code&gt; and an HTML string in &lt;code&gt;error.response.data&lt;/code&gt;. Different symptom, same cause.&lt;/p&gt;

&lt;h3&gt;
  
  
  The cross-origin variation
&lt;/h3&gt;

&lt;p&gt;If your API lives on another hostname, say &lt;code&gt;api.example.com&lt;/code&gt;, you may only see a CORS error. As far as I can tell, that's because the challenge response comes from Cloudflare, not Laravel, so the headers from your &lt;code&gt;config/cors.php&lt;/code&gt; aren't on it. The browser blocks the response before your code can read &lt;code&gt;cf-mitigated&lt;/code&gt;. Same-origin APIs avoid this, which is one more reason Sanctum's SPA setup keeps things on one domain.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Inertia variation
&lt;/h3&gt;

&lt;p&gt;Inertia apps get hit on regular page routes, not just &lt;code&gt;/api&lt;/code&gt;. After the first load, every Inertia visit is an XHR. A challenged visit shows the challenge HTML in Inertia's modal for non-Inertia responses, or just fails. Excluding &lt;code&gt;/api/&lt;/code&gt; from your rule won't help here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should you act now? Fixes in the order I'd try them
&lt;/h2&gt;

&lt;p&gt;Check &lt;strong&gt;Security &amp;gt; Events&lt;/strong&gt; in Cloudflare (the menu name may differ on your plan) and filter by your API path. If you see challenge actions on &lt;code&gt;/api/&lt;/code&gt; or on Inertia routes, act now. If you don't, I'd still add Fix 2. It's a few lines and stops a confusing failure later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fix 1: Stop challenging your API routes
&lt;/h3&gt;

&lt;p&gt;This is the standard approach. Challenge HTML page loads, where a browser can actually solve the challenge, and protect the API another way (Sanctum auth, Laravel's &lt;code&gt;throttle&lt;/code&gt; middleware, Cloudflare rate limiting).&lt;/p&gt;

&lt;p&gt;Edit the challenge rule and add a path exclusion. In our example the rule was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(ip.src.country ne "SA" and not cf.client.bot)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(ip.src.country ne "SA" and not cf.client.bot and not starts_with(http.request.uri.path, "/api/") and http.request.uri.path ne "/sanctum/csrf-cookie")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're on Inertia, a path exclusion won't cover the visits, so go straight to Fix 2.&lt;/p&gt;

&lt;p&gt;If the challenge comes from &lt;strong&gt;Bot Fight Mode&lt;/strong&gt; rather than your own rule, a custom rule can't skip it, according to Cloudflare's docs. Your choices there are turning Bot Fight Mode off or moving to a plan with configurable bot rules.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fix 2: Catch the challenge in axios and reload
&lt;/h3&gt;

&lt;p&gt;When a challenge lands on an API call, the simplest recovery is a full page reload. The browser then gets the challenge as a page, solves it, gets a fresh &lt;code&gt;cf_clearance&lt;/code&gt;, and the SPA starts working again.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;resources/js/bootstrap.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;common&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X-Requested-With&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;XMLHttpRequest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isChallenge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;403&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;?.[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cf-mitigated&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;challenge&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interceptors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isChallenge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;last&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;last&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sessionStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cfReloadAt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

            &lt;span class="c1"&gt;// Reload at most once every 30 seconds to avoid a reload loop&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;last&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;30000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;sessionStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cfReloadAt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
                &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reload&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt; &lt;span class="c1"&gt;// stop the chain while the page reloads&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;For Inertia, use its &lt;code&gt;invalid&lt;/code&gt; event, which fires on non-Inertia responses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@inertiajs/vue3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;invalid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;403&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;?.[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cf-mitigated&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;challenge&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reload&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;The shape of &lt;code&gt;event.detail.response&lt;/code&gt; can differ between Inertia versions, so log it once and check before you rely on it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The gotcha:&lt;/strong&gt; a reload only helps if the page URL itself is covered by a challenge of the same level or higher. If your rule challenges &lt;code&gt;/api/*&lt;/code&gt; but not the page, the reload passes without a challenge, no new cookie is issued, and the next API call fails again. That's what the 30 second guard is for. If you hit it, fix the rule so it covers pages, or use Fix 3. Also warn your users: a reload loses unsaved form input.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fix 3: Use Turnstile pre-clearance
&lt;/h3&gt;

&lt;p&gt;Pre-clearance lets a Turnstile widget on your page issue the &lt;code&gt;cf_clearance&lt;/code&gt; cookie, so the SPA can get cleared without a reload. You enable it on the widget in the Turnstile dashboard and pick a clearance level. That level must match or exceed your rule: per Cloudflare's docs, a Managed clearance passes Managed and Non-Interactive challenges, but not Interactive ones. The widget's hostname must also belong to the same zone.&lt;/p&gt;

&lt;p&gt;Load the script in your Blade layout and add a container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"cf-turnstile"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit"&lt;/span&gt; &lt;span class="na"&gt;async&lt;/span&gt; &lt;span class="na"&gt;defer&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then retry the request after the widget succeeds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getClearance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;turnstile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#cf-turnstile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;sitekey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_TURNSTILE_SITE_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&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;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error-callback&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&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;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Turnstile failed&lt;/span&gt;&lt;span class="dl"&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="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interceptors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isChallenge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_cfRetried&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_cfRetried&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getClearance&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;          &lt;span class="c1"&gt;// sets cf_clearance on success&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// replay the original request&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;Use this instead of the reload interceptor from Fix 2, not alongside it. Cloudflare's docs also say to validate the Turnstile token on your server. If you've done this for reCAPTCHA, it'll look familiar (the token-expiry issues in &lt;a href="https://headsntail.com/blog/google-recaptcha-v3-timeout-php-fix" rel="noopener noreferrer"&gt;this reCAPTCHA v3 timeout fix for PHP forms&lt;/a&gt; work the same way):&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;asForm&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;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'https://challenges.cloudflare.com/turnstile/v0/siteverify'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'secret'&lt;/span&gt;   &lt;span class="o"&gt;=&amp;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.turnstile.secret'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="s1"&gt;'response'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'cf_turnstile_token'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="s1"&gt;'remoteip'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nf"&gt;abort_unless&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'success'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;422&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Bot check failed.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What doesn't work
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sending &lt;code&gt;Accept: application/json&lt;/code&gt;.&lt;/strong&gt; Cloudflare decides before Laravel sees the request; your headers don't change the challenge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Raising Challenge Passage.&lt;/strong&gt; It only delays the next failure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skipping the rule when &lt;code&gt;X-Requested-With&lt;/code&gt; is present.&lt;/strong&gt; Anyone can send that header. In my opinion that's as good as having no rule.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Catching it in Laravel's exception handler.&lt;/strong&gt; The request never reached PHP.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What to watch
&lt;/h2&gt;

&lt;p&gt;Cloudflare renames and reorganizes its security products fairly often. "JS Challenge", "Non-Interactive Challenge" and "Managed Challenge" may show up differently in your dashboard than in older answers online, so check which action your rule actually uses.&lt;/p&gt;

&lt;p&gt;Keep an eye on Bot Fight Mode and similar zone-wide toggles. They can start challenging API traffic without anyone adding a rule. I'd also send a small event to your error tracker whenever the interceptor sees &lt;code&gt;cf-mitigated&lt;/code&gt;, so you find out from your logs, not your customers.&lt;/p&gt;

&lt;p&gt;If your product list was built the way &lt;a href="https://headsntail.com/blog/how-to-retrieve-data-from-database-using-vue" rel="noopener noreferrer"&gt;retrieving data from the database with Vue in Laravel&lt;/a&gt; describes, every component that calls axios gets this protection once the interceptor is in &lt;code&gt;bootstrap.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you'd like someone to look at your Cloudflare rules and Laravel setup with you, &lt;a href="https://headsntail.com/contact" rel="noopener noreferrer"&gt;contact HeadsNTail&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why does my Laravel API return 403 only behind Cloudflare?
&lt;/h3&gt;

&lt;p&gt;Cloudflare is answering the request, not Laravel. Look for &lt;code&gt;server: cloudflare&lt;/code&gt; and &lt;code&gt;cf-mitigated: challenge&lt;/code&gt; in the response headers. If they're there, the 403 came from a challenge or a bot setting, and your Laravel logs will be empty.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can a Cloudflare challenge be solved inside an AJAX request?
&lt;/h3&gt;

&lt;p&gt;No. A challenge is an HTML page that has to render and run in the browser, and an XHR or fetch call can't do that. You need a full page load or Turnstile pre-clearance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why does it work locally but fail in production?
&lt;/h3&gt;

&lt;p&gt;Your local XAMPP or &lt;code&gt;php artisan serve&lt;/code&gt; setup has no Cloudflare in front of it, so there's nothing to challenge requests. Test against the live domain, or a staging hostname proxied through Cloudflare.&lt;/p&gt;

&lt;h3&gt;
  
  
  How long does the cf_clearance cookie last?
&lt;/h3&gt;

&lt;p&gt;It lasts for the Challenge Passage duration configured on your zone. When it expires, the next challenged request fails, which is why SPAs often break after the tab has been open a while.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should I turn off Bot Fight Mode for my API?
&lt;/h3&gt;

&lt;p&gt;If it's what challenges your API calls and you can't exclude paths from it, yes, or move to a plan where bot rules are configurable. Protect the API with authentication and rate limiting instead.&lt;/p&gt;

&lt;p&gt;Next time someone tells you "the Cloudflare JS challenge is breaking my SPA", open the Network tab, look for &lt;code&gt;cf-mitigated: challenge&lt;/code&gt;, and start with Fix 1 or Fix 2.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://headsntail.com/blog/cloudflare-js-challenge-breaking-laravel-spa" rel="noopener noreferrer"&gt;headsntail.com&lt;/a&gt;. Free tools for PHP, Laravel and cPanel work: &lt;a href="https://headsntail.com/tools" rel="noopener noreferrer"&gt;headsntail.com/tools&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Setting DNS Server to Use With a Curl Request: Fix</title>
      <dc:creator>Faizan</dc:creator>
      <pubDate>Sun, 18 Oct 2026 11:07:09 +0000</pubDate>
      <link>https://dev.to/faizan050/setting-dns-server-to-use-with-a-curl-request-fix-42l4</link>
      <guid>https://dev.to/faizan050/setting-dns-server-to-use-with-a-curl-request-fix-42l4</guid>
      <description>&lt;p&gt;Can you tell curl to use a specific DNS server instead of the one configured on your computer or hosting server? Yes, but the method depends on how curl was built and whether you want to change the DNS resolver or connect to a specific IP address.&lt;/p&gt;

&lt;p&gt;If you're &lt;strong&gt;setting DNS server to use with a curl request&lt;/strong&gt;, the direct option is &lt;code&gt;--dns-servers&lt;/code&gt;, but it only works when curl uses the c-ares resolver. Other builds can use DNS-over-HTTPS with &lt;code&gt;--doh-url&lt;/code&gt;. If you already know the destination IP address, &lt;code&gt;--resolve&lt;/code&gt; lets you bypass the normal hostname lookup for that request.&lt;/p&gt;

&lt;p&gt;This tutorial covers all three methods, including PHP cURL, so you can choose the right approach without changing the DNS settings of your entire server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting DNS server to use with a curl request in 6 steps
&lt;/h2&gt;

&lt;p&gt;By default, curl uses the DNS resolution mechanism provided by its build and operating environment.&lt;/p&gt;

&lt;p&gt;On Linux, this may involve the system resolver configuration, such as &lt;code&gt;/etc/resolv.conf&lt;/code&gt; or a resolver service managed by the operating system.&lt;/p&gt;

&lt;p&gt;On Windows, DNS resolution normally follows the network's configured resolver settings when curl uses the native resolver.&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;curl https://example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before curl can connect to &lt;code&gt;example.com&lt;/code&gt;, it generally needs to determine the destination IP address.&lt;/p&gt;

&lt;p&gt;The normal request flow looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl https://example.com
         |
         v
DNS lookup
         |
         v
System-configured resolver
         |
         v
IP address returned
         |
         v
TCP/TLS connection
         |
         v
HTTPS response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sometimes the system resolver is unavailable, returns an unexpected address, or cannot resolve an internal hostname.&lt;/p&gt;

&lt;p&gt;In those cases, you may want a different DNS resolver for one request rather than modifying the server's network configuration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Confirm whether the problem is DNS resolution
&lt;/h3&gt;

&lt;p&gt;First, reproduce the request using verbose output.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-v&lt;/span&gt; https://example.com/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-v&lt;/code&gt; option displays connection details, including hostname resolution and the address curl attempts to contact.&lt;/p&gt;

&lt;p&gt;A successful lookup may produce output similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* Host example.com:443 was resolved.
* IPv4: ...
*   Trying ...
* Connected to example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact messages depend on the installed curl version and network configuration.&lt;/p&gt;

&lt;p&gt;If DNS resolution fails, you may see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl: (6) Could not resolve host: example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is curl error 6, meaning the destination hostname couldn't be resolved.&lt;/p&gt;

&lt;p&gt;You can reproduce this type of failure with a deliberately invalid hostname:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-v&lt;/span&gt; https://missing.example.invalid/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;.invalid&lt;/code&gt; domain is reserved for names that should not resolve through public DNS.&lt;/p&gt;

&lt;p&gt;If curl is using a proxy, however, the error may concern the proxy instead of the destination.&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;curl: (5) Could not resolve proxy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a different problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What to check before changing DNS:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the hostname actually exist?&lt;/li&gt;
&lt;li&gt;Is the DNS server reachable from your machine?&lt;/li&gt;
&lt;li&gt;Is curl using an HTTP or SOCKS proxy?&lt;/li&gt;
&lt;li&gt;Does the same hostname resolve through another DNS resolver?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can compare public DNS responses using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nslookup example.com 1.1.1.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This asks Cloudflare's public DNS resolver to look up &lt;code&gt;example.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If that succeeds while curl reports a resolution failure, the system resolver or curl's network path deserves closer investigation.&lt;/p&gt;

&lt;p&gt;A successful &lt;code&gt;nslookup&lt;/code&gt; doesn't automatically mean curl can reach the website. DNS lookup and HTTPS connectivity are separate operations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Use --dns-servers to select a specific DNS resolver
&lt;/h3&gt;

&lt;p&gt;The most direct curl option is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--dns-servers&lt;/span&gt; 1.1.1.1 https://example.com/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells a compatible curl build to use &lt;code&gt;1.1.1.1&lt;/code&gt; for DNS resolution instead of the system's default resolver.&lt;/p&gt;

&lt;p&gt;You can also provide multiple DNS servers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--dns-servers&lt;/span&gt; 1.1.1.1,1.0.0.1 https://example.com/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or specify a DNS port:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--dns-servers&lt;/span&gt; 1.1.1.1:53 https://example.com/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Port 53 is the normal port for conventional DNS queries.&lt;/p&gt;

&lt;p&gt;The limitation is that &lt;strong&gt;&lt;code&gt;--dns-servers&lt;/code&gt; requires curl to be built with c-ares support&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It isn't available in every curl installation.&lt;/p&gt;

&lt;h4&gt;
  
  
  Check whether curl supports c-ares
&lt;/h4&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-V&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look at the version information.&lt;/p&gt;

&lt;p&gt;A c-ares-enabled build typically identifies c-ares in its version or resolver information.&lt;/p&gt;

&lt;p&gt;Don't assume the presence of &lt;code&gt;AsynchDNS&lt;/code&gt; in the features list proves c-ares support. Curl can also perform asynchronous DNS resolution using other backends.&lt;/p&gt;

&lt;p&gt;If your build doesn't support the option, trying &lt;code&gt;--dns-servers&lt;/code&gt; may return an error indicating that the installed libcurl doesn't support it.&lt;/p&gt;

&lt;p&gt;The complete option requirements are documented in the &lt;a href="https://curl.se/docs/manpage.html" rel="noopener noreferrer"&gt;official curl DNS server documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On Windows PowerShell, explicitly use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;curl.exe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-V&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;code&gt;curl.exe&lt;/code&gt; avoids confusion with the &lt;code&gt;curl&lt;/code&gt; alias found in some Windows PowerShell environments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What to expect:&lt;/strong&gt; If your curl build supports c-ares and the DNS server is reachable, curl resolves &lt;code&gt;example.com&lt;/code&gt; through the requested resolver and proceeds with the HTTPS connection.&lt;/p&gt;

&lt;p&gt;If your curl build doesn't support c-ares, move to the next step instead of repeatedly changing DNS addresses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Use DNS-over-HTTPS when --dns-servers isn't supported
&lt;/h3&gt;

&lt;p&gt;A practical alternative is DNS-over-HTTPS, usually called DoH.&lt;/p&gt;

&lt;p&gt;Instead of sending conventional DNS queries to a resolver over port 53, curl sends DNS queries through an HTTPS endpoint.&lt;/p&gt;

&lt;p&gt;Curl provides the following option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--doh-url&lt;/span&gt; https://cloudflare-dns.com/dns-query https://example.com/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://cloudflare-dns.com/dns-query
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is Cloudflare's documented DNS-over-HTTPS endpoint.&lt;/p&gt;

&lt;p&gt;This instructs curl to use that DoH service when resolving the destination hostname.&lt;/p&gt;

&lt;p&gt;For troubleshooting, add verbose output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--doh-url&lt;/span&gt; https://cloudflare-dns.com/dns-query &lt;span class="se"&gt;\&lt;/span&gt;
  https://example.com/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The backslashes shown above are line continuations for Unix-like shells. If you're using Windows PowerShell, put the command on one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;curl.exe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--doh-url&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;https://cloudflare-dns.com/dns-query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;https://example.com/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your curl installation must support the &lt;code&gt;--doh-url&lt;/code&gt; option and the required HTTPS functionality.&lt;/p&gt;

&lt;h4&gt;
  
  
  What if curl cannot resolve the DoH server itself?
&lt;/h4&gt;

&lt;p&gt;There's a detail that often gets missed.&lt;/p&gt;

&lt;p&gt;Before curl can ask &lt;code&gt;cloudflare-dns.com&lt;/code&gt; to resolve &lt;code&gt;example.com&lt;/code&gt;, it must first connect to the DoH service.&lt;/p&gt;

&lt;p&gt;If the configured DoH service uses a hostname, its initial hostname lookup normally uses the regular resolver.&lt;/p&gt;

&lt;p&gt;That creates a bootstrap problem when your system DNS is completely unavailable.&lt;/p&gt;

&lt;p&gt;You can supply the DoH server's known IP address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--resolve&lt;/span&gt; cloudflare-dns.com:443:1.1.1.1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--doh-url&lt;/span&gt; https://cloudflare-dns.com/dns-query &lt;span class="se"&gt;\&lt;/span&gt;
  https://example.com/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;1.1.1.1&lt;/code&gt; is a documented Cloudflare resolver address.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;--resolve&lt;/code&gt; option provides the address for the DoH hostname, while &lt;code&gt;--doh-url&lt;/code&gt; tells curl where to perform the destination hostname lookup.&lt;/p&gt;

&lt;p&gt;This is useful when conventional DNS is broken but HTTPS connectivity to the DoH service is available.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Don't disable TLS certificate verification to make DNS troubleshooting easier. A certificate failure is a separate issue and should be investigated rather than bypassed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Use --resolve to connect to a specific IP address
&lt;/h3&gt;

&lt;p&gt;Sometimes you don't actually need to select another DNS server.&lt;/p&gt;

&lt;p&gt;You already know the destination IP address and simply want curl to connect there.&lt;/p&gt;

&lt;p&gt;For that situation, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--resolve hostname:port:ip-address
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, to test the known Cloudflare DoH hostname at its documented resolver address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--resolve&lt;/span&gt; cloudflare-dns.com:443:1.1.1.1 &lt;span class="se"&gt;\&lt;/span&gt;
  https://cloudflare-dns.com/dns-query
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The DoH endpoint may return an HTTP error because this request doesn't contain a DNS query. That's fine for this particular connection test. Look for successful connection and TLS verification in the verbose output.&lt;/p&gt;

&lt;p&gt;The significant part is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--resolve cloudflare-dns.com:443:1.1.1.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Curl uses the specified IP address for that hostname and port.&lt;/p&gt;

&lt;p&gt;This differs from &lt;code&gt;--dns-servers&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;--dns-servers&lt;/code&gt; option selects a resolver to answer DNS queries.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;--resolve&lt;/code&gt; option supplies an address directly, avoiding the usual DNS lookup for that hostname and port.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why --resolve is better than changing the Host header
&lt;/h4&gt;

&lt;p&gt;You might be tempted to connect to an IP address and manually set the HTTP &lt;code&gt;Host&lt;/code&gt; header.&lt;/p&gt;

&lt;p&gt;For HTTPS, that isn't always sufficient.&lt;/p&gt;

&lt;p&gt;TLS uses the requested hostname for server name indication and certificate verification.&lt;/p&gt;

&lt;p&gt;Keeping the original hostname in the URL while overriding the connection address is the cleaner approach.&lt;/p&gt;

&lt;p&gt;It's especially useful when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Testing a website before DNS records are updated.&lt;/li&gt;
&lt;li&gt;Checking a new hosting server.&lt;/li&gt;
&lt;li&gt;Comparing responses from two web servers.&lt;/li&gt;
&lt;li&gt;Investigating whether a DNS record points to the wrong address.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For another example of separating connection problems from protocol errors, see our guide to &lt;a href="https://headsntail.com/blog/nginx-curl-35-ssl3-get-record-wrong-version-number-fix" rel="noopener noreferrer"&gt;fixing curl error 35 and SSL wrong version number on Nginx&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One warning: &lt;code&gt;--resolve&lt;/code&gt; isn't a general-purpose replacement for DNS.&lt;/p&gt;

&lt;p&gt;It only applies to the hostname and port you specify. Other hostnames, including those used during redirects, may still need normal resolution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Set a custom DNS server in PHP cURL
&lt;/h3&gt;

&lt;p&gt;If you're running PHP on a hosting server, you may want the same behavior inside a PHP script.&lt;/p&gt;

&lt;p&gt;PHP's cURL extension exposes several libcurl options, including &lt;code&gt;CURLOPT_DNS_SERVERS&lt;/code&gt; when the installed PHP/libcurl combination supports it.&lt;/p&gt;

&lt;p&gt;Create a file named:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dns-test.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add:&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="nv"&gt;$url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'https://example.com/'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$ch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;curl_init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RuntimeException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'Unable to initialize cURL.'&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;defined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'CURLOPT_DNS_SERVERS'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;curl_close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RuntimeException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'CURLOPT_DNS_SERVERS is not available.'&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$dnsConfigured&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="no"&gt;CURLOPT_DNS_SERVERS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'1.1.1.1'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$dnsConfigured&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;curl_close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RuntimeException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'This libcurl build cannot set custom DNS servers.'&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;curl_setopt_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="no"&gt;CURLOPT_RETURNTRANSFER&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="no"&gt;CURLOPT_CONNECTTIMEOUT&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="no"&gt;CURLOPT_TIMEOUT&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;curl_exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'cURL Error: '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;curl_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'HTTP Status: '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt;
        &lt;span class="nb"&gt;curl_getinfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLINFO_HTTP_CODE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;curl_close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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 dns-test.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example only works when your PHP cURL extension and underlying libcurl library support the DNS server option.&lt;/p&gt;

&lt;p&gt;The PHP constant being defined doesn't guarantee that libcurl was built with c-ares.&lt;/p&gt;

&lt;p&gt;A failed &lt;code&gt;curl_setopt()&lt;/code&gt; call can also produce a PHP warning, depending on the installed extension.&lt;/p&gt;

&lt;p&gt;Check the return value rather than assuming the DNS option was applied.&lt;/p&gt;

&lt;h4&gt;
  
  
  Alternative: Use CURLOPT_RESOLVE in PHP
&lt;/h4&gt;

&lt;p&gt;When you know a hostname's IP address, you can use &lt;code&gt;CURLOPT_RESOLVE&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;Here's a complete connection test:&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="nv"&gt;$ch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;curl_init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'https://cloudflare-dns.com/dns-query'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nb"&gt;curl_setopt_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="no"&gt;CURLOPT_RESOLVE&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;'cloudflare-dns.com:443:1.1.1.1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="no"&gt;CURLOPT_RETURNTRANSFER&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="no"&gt;CURLOPT_CONNECTTIMEOUT&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="no"&gt;CURLOPT_TIMEOUT&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;curl_exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Error: '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;curl_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Connected successfully. HTTP status: '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt;
        &lt;span class="nb"&gt;curl_getinfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLINFO_HTTP_CODE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;curl_close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, a non-200 HTTP status from this DNS service is possible because we're testing connectivity without submitting a DNS question.&lt;/p&gt;

&lt;p&gt;For an ordinary application endpoint, replace the URL and resolve entry with the actual destination hostname and verified IP address.&lt;/p&gt;

&lt;p&gt;This method doesn't require the c-ares DNS resolver backend.&lt;/p&gt;

&lt;p&gt;For Laravel developers, the underlying database host concept is similar: the hostname determines where a connection should go. Our explanation of &lt;a href="https://headsntail.com/blog/mysqli-connect-host-parameter-explained" rel="noopener noreferrer"&gt;host values in MySQL connections&lt;/a&gt; covers that distinction in more detail.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6: Check proxies, DNS caches, and server configuration
&lt;/h3&gt;

&lt;p&gt;If custom DNS settings appear to make no difference, check whether curl is actually resolving the target hostname locally.&lt;/p&gt;

&lt;h4&gt;
  
  
  Check for a proxy
&lt;/h4&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-v&lt;/span&gt; https://example.com/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look for verbose messages showing proxy environment variables or a proxy connection.&lt;/p&gt;

&lt;p&gt;For a direct-connect comparison, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nt"&gt;--noproxy&lt;/span&gt; &lt;span class="s1"&gt;'*'&lt;/span&gt; https://example.com/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--noproxy '*'&lt;/code&gt; option disables proxy use for the request.&lt;/p&gt;

&lt;p&gt;If an HTTP proxy resolves the destination hostname itself, changing curl's local DNS resolver may not affect that destination lookup.&lt;/p&gt;

&lt;p&gt;SOCKS proxies can behave differently depending on the selected protocol.&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;socks5://
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;typically means the client resolves the destination hostname locally.&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;p&gt;requests hostname resolution through the SOCKS proxy.&lt;/p&gt;

&lt;p&gt;That difference matters when troubleshooting DNS.&lt;/p&gt;

&lt;h4&gt;
  
  
  Check the operating system resolver
&lt;/h4&gt;

&lt;p&gt;On Linux systems using systemd-resolved, try:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;resolvectl status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also inspect:&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="nb"&gt;cat&lt;/span&gt; /etc/resolv.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On Windows PowerShell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Get-DnsClientServerAddress&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These commands help identify the resolver settings associated with the operating system.&lt;/p&gt;

&lt;p&gt;Don't immediately edit &lt;code&gt;/etc/resolv.conf&lt;/code&gt; on a managed server. NetworkManager, systemd-resolved, a container runtime, or hosting management software may regenerate it.&lt;/p&gt;

&lt;p&gt;Changing the server's DNS configuration can affect other applications.&lt;/p&gt;

&lt;p&gt;For a one-request test, I would use &lt;code&gt;--doh-url&lt;/code&gt; or &lt;code&gt;--resolve&lt;/code&gt; before modifying system-wide DNS settings.&lt;/p&gt;

&lt;h4&gt;
  
  
  Check whether DNS caching is involved
&lt;/h4&gt;

&lt;p&gt;Curl can cache resolved addresses during a running libcurl session.&lt;/p&gt;

&lt;p&gt;For short command-line tests, starting a new curl process is a simple way to avoid reusing that process's existing DNS cache.&lt;/p&gt;

&lt;p&gt;Long-running PHP applications may reuse handles or connection pools, so cached resolution can become relevant there.&lt;/p&gt;

&lt;p&gt;Also remember that web servers and reverse proxies can have their own DNS behavior.&lt;/p&gt;

&lt;p&gt;Changing curl's resolver doesn't update a domain's authoritative DNS records, and it doesn't guarantee that every other application on the server will use the same resolver.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verify that curl is using the intended DNS method
&lt;/h2&gt;

&lt;p&gt;After applying your chosen method, run a verbose request again.&lt;/p&gt;

&lt;p&gt;For a compatible c-ares build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--dns-servers&lt;/span&gt; 1.1.1.1 &lt;span class="se"&gt;\&lt;/span&gt;
  https://example.com/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For DNS-over-HTTPS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--doh-url&lt;/span&gt; https://cloudflare-dns.com/dns-query &lt;span class="se"&gt;\&lt;/span&gt;
  https://example.com/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the DoH service with a fixed bootstrap address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--resolve&lt;/span&gt; cloudflare-dns.com:443:1.1.1.1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--doh-url&lt;/span&gt; https://cloudflare-dns.com/dns-query &lt;span class="se"&gt;\&lt;/span&gt;
  https://example.com/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look for successful name resolution, the intended connection address, a completed TLS handshake, and an HTTP response.&lt;/p&gt;

&lt;p&gt;A successful HTTP request confirms that the connection worked. It doesn't, by itself, prove which DNS server answered the lookup.&lt;/p&gt;

&lt;p&gt;For that, use curl's resolver debug output where supported or inspect DNS traffic on the machine. With DoH, the DNS exchange is encrypted, so packet inspection won't expose the DNS question without additional instrumentation.&lt;/p&gt;

&lt;p&gt;You can also try an alternate DNS service to compare results.&lt;/p&gt;

&lt;p&gt;Keep in mind that public resolvers may return different answers because of DNS caching, geographic routing, or domain-specific policies.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Can I specify a DNS server directly in a curl command?
&lt;/h3&gt;

&lt;p&gt;Yes, if curl was built with c-ares support.&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;curl &lt;span class="nt"&gt;--dns-servers&lt;/span&gt; 1.1.1.1 https://example.com/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your installed curl doesn't support that option, use a supported DNS-over-HTTPS endpoint with &lt;code&gt;--doh-url&lt;/code&gt; or supply a known destination address with &lt;code&gt;--resolve&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why does curl say "Could not resolve host" even though the website works in my browser?
&lt;/h3&gt;

&lt;p&gt;The browser and curl may use different DNS mechanisms, cached records, or proxy settings.&lt;/p&gt;

&lt;p&gt;Some browsers can use their own DNS-over-HTTPS configuration, while curl may rely on the operating system resolver.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;curl -v&lt;/code&gt; and compare the results with &lt;code&gt;nslookup&lt;/code&gt; to identify where hostname resolution is failing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does CURLOPT_DNS_SERVERS work on every PHP hosting server?
&lt;/h3&gt;

&lt;p&gt;No. The option depends on the libcurl library that PHP uses, and selecting custom conventional DNS servers requires the c-ares resolver backend.&lt;/p&gt;

&lt;p&gt;Some shared hosting environments don't provide that capability.&lt;/p&gt;

&lt;p&gt;If it isn't available, consider a supported DoH option, &lt;code&gt;CURLOPT_RESOLVE&lt;/code&gt; for a known address, or an approved server-level DNS change.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's the difference between --dns-servers and --resolve in curl?
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;--dns-servers&lt;/code&gt; tells curl which DNS server should resolve hostnames.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--resolve&lt;/code&gt; provides a specific IP address for a hostname and port, bypassing the normal DNS lookup for that entry.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;--dns-servers&lt;/code&gt; when you want an alternate resolver. Use &lt;code&gt;--resolve&lt;/code&gt; when you already know the destination address and need to test that specific server.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I use Google or Cloudflare DNS without changing my server settings?
&lt;/h3&gt;

&lt;p&gt;Yes, provided your curl build and network environment support the chosen method.&lt;/p&gt;

&lt;p&gt;For Cloudflare, a compatible c-ares build can use &lt;code&gt;--dns-servers 1.1.1.1&lt;/code&gt;. Alternatively, a DoH-capable build can use Cloudflare's HTTPS DNS endpoint.&lt;/p&gt;

&lt;p&gt;For Google's public DNS service, the conventional resolver addresses include &lt;code&gt;8.8.8.8&lt;/code&gt; and &lt;code&gt;8.8.4.4&lt;/code&gt;. Select a resolver that your network policy permits and that supports your application's requirements.&lt;/p&gt;

&lt;p&gt;If you need help diagnosing a hosting-specific DNS or PHP cURL configuration, &lt;a href="https://headsntail.com/contact" rel="noopener noreferrer"&gt;contact HeadsNTail&lt;/a&gt; with the curl version information and the relevant error output.&lt;/p&gt;

&lt;p&gt;The next step after &lt;strong&gt;setting dns server to use with a curl request&lt;/strong&gt; is to test the same URL with both your default resolver and the selected alternative, then keep the smallest configuration change that fixes the actual problem.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://headsntail.com/blog/setting-dns-server-to-use-with-curl-request" rel="noopener noreferrer"&gt;headsntail.com&lt;/a&gt;. Free tools for PHP, Laravel and cPanel work: &lt;a href="https://headsntail.com/tools" rel="noopener noreferrer"&gt;headsntail.com/tools&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>devops</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Retrieve Data From Database Using Vue in Laravel</title>
      <dc:creator>Faizan</dc:creator>
      <pubDate>Sun, 18 Oct 2026 09:15:16 +0000</pubDate>
      <link>https://dev.to/faizan050/how-to-retrieve-data-from-database-using-vue-in-laravel-14ip</link>
      <guid>https://dev.to/faizan050/how-to-retrieve-data-from-database-using-vue-in-laravel-14ip</guid>
      <description>&lt;p&gt;HNT-START&lt;br&gt;
TITLE: How to Retrieve Data From Database Using Vue in Laravel&lt;br&gt;
SLUG: how-to-retrieve-data-from-database-using-vue&lt;br&gt;
EXCERPT: Learn how to fetch MySQL records in Laravel using Vue 3, Eloquent, JSON routes, and the Fetch API, with working code and fixes for common errors.&lt;/p&gt;
&lt;h2&gt;
  
  
  CATEGORY: Laravel
&lt;/h2&gt;

&lt;p&gt;Your Vue component shows an empty list even though your Laravel database contains records. You can fix this by creating a Laravel JSON endpoint, fetching its response with Vue, and displaying the results using &lt;code&gt;v-for&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you're searching for &lt;strong&gt;how to retrieve data from database using vue&lt;/strong&gt;, the correct approach is to let Laravel handle the database connection and send the results to Vue as JSON. Vue uses &lt;code&gt;fetch()&lt;/code&gt; or Axios to request that data, stores it in a reactive variable, and updates the page automatically.&lt;/p&gt;

&lt;p&gt;We'll build a working product listing using Laravel, MySQL, Vue 3, and Vite. The final page will load product names and prices directly from your database, with proper loading and error handling.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to retrieve data from database using Vue in Laravel: 6 steps
&lt;/h2&gt;

&lt;p&gt;Before writing code, understand how Laravel and Vue communicate.&lt;/p&gt;

&lt;p&gt;Vue runs in the browser. It cannot directly execute Laravel's Eloquent queries or access your MySQL database securely.&lt;/p&gt;

&lt;p&gt;Laravel runs on the server. It reads database records and returns the information that the frontend needs.&lt;/p&gt;

&lt;p&gt;The request follows this flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User opens /products
        |
        v
Laravel returns Blade page
        |
        v
Vue component loads
        |
        v
fetch('/api/products')
        |
        v
Laravel ProductController
        |
        v
Product::get()
        |
        v
MySQL products table
        |
        v
JSON response
        |
        v
Vue displays products
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This separation is important.&lt;/p&gt;

&lt;p&gt;You don't put SQL queries inside Vue components, and you don't need to reload the entire page every time the displayed data changes.&lt;/p&gt;

&lt;p&gt;For this example, we'll use an existing Laravel application with Vue 3 installed through npm. If Vue isn't installed yet, the setup is included below.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Configure the Laravel MySQL database connection
&lt;/h3&gt;

&lt;p&gt;Open your Laravel project's &lt;code&gt;.env&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Find the database settings and update them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=vue_demo
DB_USERNAME=root
DB_PASSWORD=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These values assume a local MySQL development environment.&lt;/p&gt;

&lt;p&gt;Change the username and password according to your MySQL configuration. For production applications, use a dedicated database account with appropriate permissions instead of root.&lt;/p&gt;

&lt;p&gt;The database must exist before Laravel can create tables inside it.&lt;/p&gt;

&lt;p&gt;Open phpMyAdmin or a MySQL command-line session and execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;vue_demo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now clear Laravel's cached configuration:&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;If you're using XAMPP, make sure MySQL is running in the XAMPP Control Panel.&lt;/p&gt;

&lt;p&gt;You can confirm that MySQL accepts connections by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mysql &lt;span class="nt"&gt;-h&lt;/span&gt; 127.0.0.1 &lt;span class="nt"&gt;-P&lt;/span&gt; 3306 &lt;span class="nt"&gt;-u&lt;/span&gt; root &lt;span class="nt"&gt;-p&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enter the configured MySQL password when prompted.&lt;/p&gt;

&lt;p&gt;If the account has no password in your local environment, use the appropriate login settings.&lt;/p&gt;

&lt;p&gt;Once connected, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt; &lt;span class="n"&gt;DATABASES&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see &lt;code&gt;vue_demo&lt;/code&gt; in the results.&lt;/p&gt;

&lt;p&gt;If Laravel reports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SQLSTATE[HY000] [2002] Connection refused
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check whether MySQL is running and whether the port matches your &lt;code&gt;.env&lt;/code&gt; configuration.&lt;/p&gt;

&lt;p&gt;If you see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SQLSTATE[HY000] [1045] Access denied for user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check your credentials and database permissions.&lt;/p&gt;

&lt;p&gt;For a closer explanation of local and remote MySQL connections, read our guide to &lt;a href="https://headsntail.com/blog/mysqli-connect-host-parameter-explained" rel="noopener noreferrer"&gt;the host parameter in MySQL connections&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What to expect:&lt;/strong&gt; Laravel now has the connection settings needed to access the &lt;code&gt;vue_demo&lt;/code&gt; database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Create the Product model and products table
&lt;/h3&gt;

&lt;p&gt;We'll use a small products table so it's easy to see exactly where the data comes from.&lt;/p&gt;

&lt;p&gt;Run this command in your Laravel project directory:&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 make:model Product &lt;span class="nt"&gt;-m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Laravel creates a model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/Models/Product.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And a migration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;database/migrations/xxxx_xx_xx_xxxxxx_create_products_table.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The timestamp in the migration filename will be different in your project.&lt;/p&gt;

&lt;p&gt;Open the migration file and replace its contents with:&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;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Database\Migrations\Migration&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\Database\Schema\Blueprint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Schema&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Migration&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;up&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;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'products'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Blueprint&lt;/span&gt; &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'price'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;timestamps&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="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;down&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;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;dropIfExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'products'&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;This creates a table with the following columns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;id
name
price
created_at
updated_at
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;id&lt;/code&gt; column is the primary key.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;price&lt;/code&gt; column uses &lt;code&gt;decimal(10,2)&lt;/code&gt;, which is appropriate for storing fixed-precision prices in this example.&lt;/p&gt;

&lt;p&gt;Next, open:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/Models/Product.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update it:&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\Models&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\Database\Eloquent\Model&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;Product&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$fillable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'price'&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;The &lt;code&gt;$fillable&lt;/code&gt; property allows these fields to be assigned when using Eloquent's &lt;code&gt;create()&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;Now execute:&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 migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Laravel should report that the products migration ran successfully.&lt;/p&gt;

&lt;p&gt;If you already have a &lt;code&gt;products&lt;/code&gt; table, don't run a duplicate table-creation migration. Use your existing table structure or create a migration that changes only the columns you need.&lt;/p&gt;

&lt;h4&gt;
  
  
  Insert sample records
&lt;/h4&gt;

&lt;p&gt;Open Laravel Tinker:&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 tinker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Insert some products:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;\App\Models\Product&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Laptop'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'price'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;2500.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nc"&gt;\App\Models\Product&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Keyboard'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'price'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;150.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nc"&gt;\App\Models\Product&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Mouse'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'price'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;75.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nc"&gt;\App\Models\Product&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Monitor'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'price'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;850.00&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;You should see Eloquent model output after each successful insertion.&lt;/p&gt;

&lt;p&gt;Exit Tinker:&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;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the records in MySQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a new, empty table, the result should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+----+----------+---------+
| id | name     | price   |
+----+----------+---------+
|  1 | Laptop   | 2500.00 |
|  2 | Keyboard |  150.00 |
|  3 | Mouse    |   75.00 |
|  4 | Monitor  |  850.00 |
+----+----------+---------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your table already contained data, the IDs may be different.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What to expect:&lt;/strong&gt; Four product records are now stored in MySQL and can be retrieved through Laravel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Create a Laravel controller to fetch MySQL records
&lt;/h3&gt;

&lt;p&gt;Vue needs an HTTP endpoint that returns product data.&lt;/p&gt;

&lt;p&gt;We'll create that endpoint using a Laravel controller.&lt;/p&gt;

&lt;p&gt;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 make:controller ProductController
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/Http/Controllers/ProductController.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the contents with:&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\Http\Controllers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Models\Product&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Http\JsonResponse&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;ProductController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Controller&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;JsonResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Product&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;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'price'&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;orderBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'asc'&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;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$products&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;This is where Laravel retrieves data from MySQL.&lt;/p&gt;

&lt;p&gt;Let's examine the query.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Product&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creates an Eloquent query for the &lt;code&gt;products&lt;/code&gt; table.&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="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'price'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Selects only the fields needed by the frontend.&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="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;orderBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'asc'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sorts the records by ID.&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="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Executes the query and retrieves the matching products.&lt;/p&gt;

&lt;p&gt;Finally:&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;return&lt;/span&gt; &lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$products&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Converts the result into a JSON HTTP response.&lt;/p&gt;

&lt;p&gt;For this type of application, returning JSON is better than sending generated HTML from the controller. Vue can decide how to display the records without changing the backend response.&lt;/p&gt;

&lt;p&gt;There's also no need to return every column from the database.&lt;/p&gt;

&lt;p&gt;For example, if your products table later contains internal costs or supplier information, those fields shouldn't automatically become visible to every frontend user.&lt;/p&gt;

&lt;p&gt;When working with more complex conditions, our tutorial on &lt;a href="https://headsntail.com/blog/select-multiple-columns-based-on-condition-sql" rel="noopener noreferrer"&gt;selecting SQL columns based on conditions&lt;/a&gt; covers the database-query side.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What to expect:&lt;/strong&gt; Your controller can retrieve the product records and return only the selected fields.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Create a Laravel route that Vue can call
&lt;/h3&gt;

&lt;p&gt;Now we need a URL for the controller.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;routes/web.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add:&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;App\Http\Controllers\ProductController&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Route&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/api/products'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;ProductController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'index'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/products'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'products'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first route returns JSON:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /api/products
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second route displays the page that will contain our Vue component:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Why put these routes inside &lt;code&gt;web.php&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;For this tutorial, Vue and Laravel use the same origin. A JSON GET route inside &lt;code&gt;web.php&lt;/code&gt; is enough, and it works without installing Laravel's optional API routing setup.&lt;/p&gt;

&lt;p&gt;If you're building a separate REST API, you can use &lt;code&gt;routes/api.php&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;In Laravel installations where API routing hasn't been configured, you can enable it using:&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 &lt;span class="nb"&gt;install&lt;/span&gt;:api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That command may also install API authentication-related dependencies and generate additional files. It isn't required for this example.&lt;/p&gt;

&lt;p&gt;If you define a route in &lt;code&gt;routes/api.php&lt;/code&gt;, remember that Laravel normally applies the &lt;code&gt;/api&lt;/code&gt; prefix automatically.&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="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/products'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;ProductController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'index'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Would become:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Don't accidentally define &lt;code&gt;/api/products&lt;/code&gt; inside &lt;code&gt;api.php&lt;/code&gt; and end up requesting &lt;code&gt;/api/api/products&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Test the JSON endpoint before writing Vue
&lt;/h4&gt;

&lt;p&gt;Start Laravel:&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 serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open this URL in your browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://127.0.0.1:8000/api/products
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response should resemble:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Laptop"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2500.00"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Keyboard"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"150.00"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Mouse"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"75.00"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Monitor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"850.00"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that &lt;code&gt;price&lt;/code&gt; may be returned as a string.&lt;/p&gt;

&lt;p&gt;This is normal when MySQL decimal values are serialized through Laravel.&lt;/p&gt;

&lt;p&gt;If the endpoint doesn't return records, stop here and investigate the Laravel response.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't start changing Vue code to fix a broken controller or database connection.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Install Vue 3 and connect it to Laravel Vite
&lt;/h3&gt;

&lt;p&gt;Laravel uses Vite to build frontend assets.&lt;/p&gt;

&lt;p&gt;We'll install Vue 3 and its Vite plugin.&lt;/p&gt;

&lt;p&gt;From the Laravel project directory, execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;vue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install the Vue plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; @vitejs/plugin-vue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now open:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vite.config.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a standard Laravel project with JavaScript and CSS entry points, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;laravel&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;laravel-vite-plugin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;vue&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@vitejs/plugin-vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nf"&gt;laravel&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;resources/css/app.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;resources/js/app.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="na"&gt;refresh&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}),&lt;/span&gt;
        &lt;span class="nf"&gt;vue&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;If the project already has custom Vite plugins or asset paths, preserve them and add Vue support to the existing configuration.&lt;/p&gt;

&lt;p&gt;Next, open:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resources/js/app.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace or adjust it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./bootstrap&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createApp&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ProductsList&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/ProductsList.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;createApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ProductsList&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;mount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;createApp()&lt;/code&gt; function initializes Vue.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;mount('#app')&lt;/code&gt; instruction tells Vue where to render the component.&lt;/p&gt;

&lt;p&gt;Later, our Blade page will contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vue will mount inside that element.&lt;/p&gt;

&lt;p&gt;This is a common place where developers get confused.&lt;/p&gt;

&lt;p&gt;Laravel Blade and Vue can work together, but they do different jobs.&lt;/p&gt;

&lt;p&gt;Blade generates the initial HTML page on the server. Vue runs in the browser after the JavaScript loads.&lt;/p&gt;

&lt;p&gt;You don't need to transfer every database record into Blade variables when Vue is already fetching a JSON endpoint.&lt;/p&gt;

&lt;p&gt;For projects that mix server-rendered values and JavaScript components, see &lt;a href="https://headsntail.com/blog/how-to-set-variables-laravel-blade-template" rel="noopener noreferrer"&gt;how to set variables in Laravel Blade templates&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What to expect:&lt;/strong&gt; Laravel Vite is now configured to compile and load Vue single-file components.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6: Retrieve and display Laravel database records in Vue
&lt;/h3&gt;

&lt;p&gt;Create this folder if it doesn't exist:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Inside that folder, create:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ProductsList.vue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onMounted&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadProducts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/products&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="s2"&gt;`Failed to load products: HTTP &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unexpected API response format&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&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="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;loadProducts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;main&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"products-page"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Products&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
            &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt;
            &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"loadProducts"&lt;/span&gt;
            &lt;span class="na"&gt;:disabled=&lt;/span&gt;&lt;span class="s"&gt;"loading"&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Loading...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Refresh products&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"loading"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            Loading products...
        &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;v-else-if=&lt;/span&gt;&lt;span class="s"&gt;"error"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;v-else-if=&lt;/span&gt;&lt;span class="s"&gt;"products.length === 0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            No products found.
        &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;table&lt;/span&gt; &lt;span class="na"&gt;v-else&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;thead&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;ID&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Product name&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;Price&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/thead&amp;gt;&lt;/span&gt;

            &lt;span class="nt"&gt;&amp;lt;tbody&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt;
                    &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"product in products"&lt;/span&gt;
                    &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"product.id"&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;
                        &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/tbody&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;style&lt;/span&gt; &lt;span class="na"&gt;scoped&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nc"&gt;.products-page&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;900px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;40px&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Arial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;table&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-collapse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;collapse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;td&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#ddd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;12px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;left&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;th&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#f5f5f5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt; &lt;span class="m"&gt;16px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;style&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This component does more than simply fetch records.&lt;/p&gt;

&lt;p&gt;It handles the initial request, shows a loading state, detects unsuccessful HTTP responses, checks the returned data format, and displays an error if the request fails.&lt;/p&gt;

&lt;p&gt;It also includes a refresh button so you can reload products without refreshing the entire Laravel page.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why ref() matters
&lt;/h4&gt;

&lt;p&gt;Look at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vue's &lt;code&gt;ref()&lt;/code&gt; creates reactive state.&lt;/p&gt;

&lt;p&gt;When this line executes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vue detects the change and updates the table.&lt;/p&gt;

&lt;p&gt;You don't need to manually rebuild the HTML or call a DOM update function.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why onMounted() is used
&lt;/h4&gt;

&lt;p&gt;This code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;loadProducts&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;Runs after the component mounts.&lt;/p&gt;

&lt;p&gt;It's a natural place to load the initial data for a client-rendered product listing.&lt;/p&gt;

&lt;p&gt;Avoid putting the same fetch request in multiple lifecycle hooks unless you specifically need multiple requests.&lt;/p&gt;

&lt;p&gt;Otherwise, you may accidentally load the data twice.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why response.ok should be checked
&lt;/h4&gt;

&lt;p&gt;The Fetch API doesn't automatically reject a promise when a server returns an HTTP error such as 404 or 500.&lt;/p&gt;

&lt;p&gt;That's why we check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s2"&gt;`Failed to load products: HTTP &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;Without this check, your code could attempt to display an error response as if it contained products.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why v-for needs a unique key
&lt;/h4&gt;

&lt;p&gt;The table contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt;
    &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"product in products"&lt;/span&gt;
    &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"product.id"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;v-for&lt;/code&gt; directive repeats the row for each product.&lt;/p&gt;

&lt;p&gt;The key helps Vue identify which record belongs to each rendered row when the list changes.&lt;/p&gt;

&lt;p&gt;Use a stable database ID rather than the array index when an ID is available.&lt;/p&gt;

&lt;h4&gt;
  
  
  Create the Laravel Blade page
&lt;/h4&gt;

&lt;p&gt;Now create:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resources/views/products.blade.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add:&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;!DOCTYPE html&amp;gt;
&amp;lt;html lang="en"&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset="UTF-8"&amp;gt;

    &amp;lt;meta
        name="viewport"
        content="width=device-width, initial-scale=1"
    &amp;gt;

    &amp;lt;title&amp;gt;Laravel Vue Products&amp;lt;/title&amp;gt;

    @vite([
        'resources/css/app.css',
        'resources/js/app.js'
    ])
&amp;lt;/head&amp;gt;

&amp;lt;body&amp;gt;

    &amp;lt;div id="app"&amp;gt;&amp;lt;/div&amp;gt;

&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Blade file doesn't need to query the database.&lt;/p&gt;

&lt;p&gt;It simply provides the HTML document, Vite assets, and mounting element.&lt;/p&gt;

&lt;p&gt;Vue takes care of requesting and displaying the products.&lt;/p&gt;

&lt;p&gt;Start the frontend development server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep the Laravel development server running in another terminal:&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 serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now visit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://127.0.0.1:8000/products
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see a table containing the product records from MySQL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verify that Vue is fetching real MySQL data
&lt;/h2&gt;

&lt;p&gt;Open the browser's developer tools and switch to the Network tab.&lt;/p&gt;

&lt;p&gt;Refresh the products page.&lt;/p&gt;

&lt;p&gt;Look for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /api/products
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Click the request and inspect its status.&lt;/p&gt;

&lt;p&gt;A successful response should show:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Status: 200 OK
Content-Type: application/json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Response or Preview tab should contain the product records.&lt;/p&gt;

&lt;p&gt;Your page should display something similar to:&lt;br&gt;
&lt;/p&gt;

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

[Refresh products]

ID   Product name    Price
1    Laptop          2500.00
2    Keyboard         150.00
3    Mouse             75.00
4    Monitor          850.00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To confirm that Vue is displaying live database content rather than hardcoded values, open Tinker:&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 tinker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Insert another record:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;\App\Models\Product&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'USB Cable'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'price'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;25.00&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;Exit Tinker and click the &lt;strong&gt;Refresh products&lt;/strong&gt; button.&lt;/p&gt;

&lt;p&gt;The new product should appear.&lt;/p&gt;

&lt;p&gt;No changes to the Vue source code are needed.&lt;/p&gt;

&lt;p&gt;That confirms the complete connection from MySQL through Laravel to the browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix Vue showing an empty list when Laravel has records
&lt;/h2&gt;

&lt;p&gt;If the table still doesn't show anything, diagnose the problem from the backend toward the frontend.&lt;/p&gt;

&lt;p&gt;That order is faster than changing unrelated Vue settings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Laravel API returns 404 Not Found
&lt;/h3&gt;

&lt;p&gt;First, check your route:&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:list &lt;span class="nt"&gt;--path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;api/products
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see a GET route pointing to &lt;code&gt;ProductController&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If it isn't present, check &lt;code&gt;routes/web.php&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can also clear route caching:&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:clear
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure the frontend requests the correct path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/products&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A small mismatch between &lt;code&gt;/api/product&lt;/code&gt; and &lt;code&gt;/api/products&lt;/code&gt; is enough to return 404.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vue returns Unexpected token '&amp;lt;', "&amp;lt;!DOCTYPE" is not valid JSON
&lt;/h3&gt;

&lt;p&gt;This error means the response is HTML, not the JSON that &lt;code&gt;response.json()&lt;/code&gt; expected.&lt;/p&gt;

&lt;p&gt;Common reasons include an incorrect route, a Laravel error page, or a redirect to a login screen.&lt;/p&gt;

&lt;p&gt;Open the browser Network tab and inspect the response body.&lt;/p&gt;

&lt;p&gt;If it contains an HTML document, find out why the server returned that document.&lt;/p&gt;

&lt;p&gt;Don't try to fix the issue by replacing every &lt;code&gt;response.json()&lt;/code&gt; call with &lt;code&gt;response.text()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That changes how the response is parsed but doesn't solve the underlying API problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  API returns an empty array
&lt;/h3&gt;

&lt;p&gt;Suppose &lt;code&gt;/api/products&lt;/code&gt; returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That means Laravel successfully returned an empty collection.&lt;/p&gt;

&lt;p&gt;Check the records directly:&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 tinker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;\App\Models\Product&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;\App\Models\Product&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the count is zero, your configured database doesn't contain the expected records.&lt;/p&gt;

&lt;p&gt;Check &lt;code&gt;DB_DATABASE&lt;/code&gt;, the active environment, and any query conditions.&lt;/p&gt;

&lt;p&gt;A frequent mistake is inserting records into one database through phpMyAdmin while Laravel is connected to another.&lt;/p&gt;

&lt;h3&gt;
  
  
  Laravel returns a 500 server error
&lt;/h3&gt;

&lt;p&gt;A 500 response means the server encountered an error while processing the request.&lt;/p&gt;

&lt;p&gt;Inspect Laravel's application logs under:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;The actual filename depends on the configured logging channel.&lt;/p&gt;

&lt;p&gt;Look for SQL exceptions, missing tables, incorrect model names, or PHP errors.&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;SQLSTATE[42S02]: Base table or view not found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usually means the expected table doesn't exist in the connected database.&lt;/p&gt;

&lt;p&gt;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 migrate:status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check whether the products migration was applied.&lt;/p&gt;

&lt;p&gt;Don't assume every 500 error is caused by Vue. The browser is only reporting that Laravel failed to complete the request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vue displays nothing and no request is sent
&lt;/h3&gt;

&lt;p&gt;If the Network tab doesn't show &lt;code&gt;/api/products&lt;/code&gt;, the Vue component may not be mounting.&lt;/p&gt;

&lt;p&gt;Check your &lt;code&gt;app.js&lt;/code&gt; import:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ProductsList&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/ProductsList.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the mounting instruction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;createApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ProductsList&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;mount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then confirm the Blade view contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also inspect the browser Console tab for Vite compilation or module-loading errors.&lt;/p&gt;

&lt;p&gt;If you're running locally, make sure Vite is running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a production build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deploy the generated frontend assets with the Laravel application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fetch works locally but fails because of CORS
&lt;/h3&gt;

&lt;p&gt;Cross-origin errors occur when the browser requests a different origin without the required permissions.&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;Vue frontend:
http://localhost:5173

Laravel backend:
http://127.0.0.1:8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are different origins.&lt;/p&gt;

&lt;p&gt;If you host Vue separately, configure Laravel's CORS settings for the intended frontend origin and use the correct API URL.&lt;/p&gt;

&lt;p&gt;For a browser request using credentials, the server also needs appropriate credentials and origin settings.&lt;/p&gt;

&lt;p&gt;Don't disable browser security to make the request work.&lt;/p&gt;

&lt;p&gt;The setup in this tutorial avoids the issue by serving the Vue page and API endpoint from the same Laravel origin.&lt;/p&gt;

&lt;h3&gt;
  
  
  The product list doesn't update after adding records
&lt;/h3&gt;

&lt;p&gt;The component loads products when it mounts.&lt;/p&gt;

&lt;p&gt;It won't automatically know that a different user added another product to MySQL.&lt;/p&gt;

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

&lt;p&gt;The refresh button calls &lt;code&gt;loadProducts()&lt;/code&gt; again and retrieves the latest records.&lt;/p&gt;

&lt;p&gt;If you add product creation or editing forms later, call &lt;code&gt;loadProducts()&lt;/code&gt; after a successful save.&lt;/p&gt;

&lt;p&gt;For applications that need continuous updates, consider polling or a real-time broadcasting approach. Neither is necessary for a basic product listing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use pagination when the products table becomes large
&lt;/h2&gt;

&lt;p&gt;The original controller uses:&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="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That retrieves all matching records.&lt;/p&gt;

&lt;p&gt;It's fine for a small example, but retrieving every row can become expensive as the table grows.&lt;/p&gt;

&lt;p&gt;Laravel provides pagination through Eloquent.&lt;/p&gt;

&lt;p&gt;Update the controller method:&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;index&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;JsonResponse&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Product&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;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'price'&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;orderBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'id'&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;paginate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$products&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 endpoint returns a paginated response rather than a plain array.&lt;/p&gt;

&lt;p&gt;The JSON contains the product records under &lt;code&gt;data&lt;/code&gt;, alongside pagination metadata.&lt;/p&gt;

&lt;p&gt;You'll need to change the Vue assignment from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&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 javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because the response structure has changed.&lt;/p&gt;

&lt;p&gt;Also remove or adjust the earlier &lt;code&gt;Array.isArray(data)&lt;/code&gt; check, since the top-level response is now an object.&lt;/p&gt;

&lt;p&gt;For example, the relevant parsing code becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unexpected pagination response&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Laravel also provides metadata such as the current page and last page, which you can use to build pagination controls.&lt;/p&gt;

&lt;p&gt;The next page can be requested through:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/products?page=2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'd use Laravel's built-in pagination instead of writing manual SQL &lt;code&gt;LIMIT&lt;/code&gt; and &lt;code&gt;OFFSET&lt;/code&gt; handling for an ordinary product list.&lt;/p&gt;

&lt;p&gt;For an existing project with custom routing or database issues, &lt;a href="https://headsntail.com/services" rel="noopener noreferrer"&gt;HeadsNTail services&lt;/a&gt; is available for hands-on development assistance.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Can Vue connect directly to a MySQL database?
&lt;/h3&gt;

&lt;p&gt;No. A browser-based Vue application shouldn't open a direct MySQL connection.&lt;/p&gt;

&lt;p&gt;Database credentials and server-side queries belong in Laravel. Vue should communicate with Laravel through an HTTP endpoint that returns only the data the user is authorized to access.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I fetch data from Laravel API using Axios in Vue 3?
&lt;/h3&gt;

&lt;p&gt;Install Axios:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;axios
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then use it inside a Vue component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onMounted&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;

&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/products&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Failed to load products:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&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;Axios automatically parses JSON responses in ordinary cases.&lt;/p&gt;

&lt;p&gt;The existing Laravel controller doesn't need to change. This example assumes the endpoint returns a plain array, not a paginated response.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I display data from a Laravel database in a Vue table?
&lt;/h3&gt;

&lt;p&gt;Fetch the records from a Laravel endpoint and store them in a reactive array.&lt;/p&gt;

&lt;p&gt;Then use &lt;code&gt;v-for&lt;/code&gt; to generate the table rows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt; &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"product in products"&lt;/span&gt; &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"product.id"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;{{ product.name }}&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;{{ product.price }}&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vue will update the table whenever the reactive array changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I get a single database record in Vue using Laravel?
&lt;/h3&gt;

&lt;p&gt;Create a Laravel route that accepts a product ID:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/api/products/{product}'&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="nc"&gt;\App\Models\Product&lt;/span&gt; &lt;span class="nv"&gt;$product&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nv"&gt;$product&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;only&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'price'&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;Laravel route model binding retrieves the matching product or returns a 404 response if it doesn't exist.&lt;/p&gt;

&lt;p&gt;Fetch the record from Vue:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/products/1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`HTTP &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For private records, add the appropriate authentication and authorization checks before returning them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is Vue showing an empty array when MySQL has data?
&lt;/h3&gt;

&lt;p&gt;First, open the Laravel API endpoint directly and inspect the JSON.&lt;/p&gt;

&lt;p&gt;If Laravel returns &lt;code&gt;[]&lt;/code&gt;, check the Eloquent query and the database configured in &lt;code&gt;.env&lt;/code&gt;. If Laravel returns records but Vue doesn't display them, check the component's response parsing, reactive state, and browser console.&lt;/p&gt;

&lt;p&gt;For the next step after learning &lt;strong&gt;how to retrieve data from database using vue&lt;/strong&gt;, add server-side search and pagination, then protect any endpoints that expose private data.&lt;/p&gt;

&lt;p&gt;HNT-END&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://headsntail.com/blog/how-to-retrieve-data-from-database-using-vue" rel="noopener noreferrer"&gt;headsntail.com&lt;/a&gt;. Free tools for PHP, Laravel and cPanel work: &lt;a href="https://headsntail.com/tools" rel="noopener noreferrer"&gt;headsntail.com/tools&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>BeanCreationException: Database Type NONE MySQL Fix</title>
      <dc:creator>Faizan</dc:creator>
      <pubDate>Sun, 18 Oct 2026 08:14:36 +0000</pubDate>
      <link>https://dev.to/faizan050/beancreationexception-database-type-none-mysql-fix-2hci</link>
      <guid>https://dev.to/faizan050/beancreationexception-database-type-none-mysql-fix-2hci</guid>
      <description>&lt;p&gt;You can fix this Spring Boot database startup failure in about 10 minutes by correcting the JDBC configuration and checking that the MySQL driver is available.&lt;/p&gt;

&lt;p&gt;The error usually appears as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;org.springframework.beans.factory.BeanCreationException:
Cannot determine embedded database driver class for database type NONE.
If you want an embedded database please put a supported one on the classpath.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A missing &lt;code&gt;spring.datasource.url&lt;/code&gt; is the most common configuration mistake.&lt;/p&gt;

&lt;p&gt;A missing MySQL JDBC driver can also prevent Spring Boot from creating a working database connection.&lt;/p&gt;

&lt;p&gt;Another frequent cause is placing valid database settings in a configuration file or Spring profile that isn't being loaded.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick answer:&lt;/strong&gt; The error &lt;code&gt;beancreationexception: cannot determine embedded database driver class for database type none&lt;/code&gt; means Spring Boot couldn't determine which JDBC driver to use while creating its DataSource. Add the MySQL connection URL, username, password, and Connector/J dependency. Then check that the correct application configuration and Spring profile are active.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick fix: BeanCreationException: Cannot determine embedded database driver class for database type NONE
&lt;/h2&gt;

&lt;p&gt;Start with the application's database configuration. This resolves the problem when Spring Boot is missing the JDBC connection details.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Configure MySQL in application.properties
&lt;/h3&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/main/resources/application.properties
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add these settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;spring.datasource.url&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;jdbc:mysql://127.0.0.1:3306/appdb&lt;/span&gt;
&lt;span class="py"&gt;spring.datasource.username&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;appuser&lt;/span&gt;
&lt;span class="py"&gt;spring.datasource.password&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;your_password&lt;/span&gt;
&lt;span class="py"&gt;spring.datasource.driver-class-name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;com.mysql.cj.jdbc.Driver&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;127.0.0.1&lt;/code&gt; with your MySQL server address.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;3306&lt;/code&gt; with the configured MySQL port.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;appdb&lt;/code&gt; with your existing database name.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;appuser&lt;/code&gt; and &lt;code&gt;your_password&lt;/code&gt; with valid database credentials.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are example values, not credentials that will work automatically.&lt;/p&gt;

&lt;p&gt;For production, keep passwords outside source control and supply them through your deployment's secret or environment configuration.&lt;/p&gt;

&lt;p&gt;Spring Boot can normally determine the MySQL driver from a valid JDBC URL. The explicit &lt;code&gt;driver-class-name&lt;/code&gt; setting is useful for troubleshooting, but isn't usually required.&lt;/p&gt;

&lt;p&gt;The important property is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;spring.datasource.url&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;jdbc:mysql://127.0.0.1:3306/appdb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without that URL, Spring Boot may attempt to find an embedded database instead.&lt;/p&gt;

&lt;p&gt;This behavior is documented in the &lt;a href="https://docs.spring.io/spring-boot/reference/data/sql.html" rel="noopener noreferrer"&gt;Spring Boot SQL database configuration reference&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Add the MySQL JDBC dependency
&lt;/h3&gt;

&lt;p&gt;Open your Maven project's &lt;code&gt;pom.xml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For a Spring Boot project using its supported dependency management, add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.mysql&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;mysql-connector-j&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;runtime&lt;span class="nt"&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Place it inside the existing &lt;code&gt;&amp;lt;dependencies&amp;gt;&lt;/code&gt; section.&lt;/p&gt;

&lt;p&gt;Spring Boot's dependency management supplies the compatible version when your project uses its managed dependency definitions.&lt;/p&gt;

&lt;p&gt;If your project doesn't use Spring Boot dependency management, you'll need to specify a Connector/J version compatible with your Java and MySQL setup.&lt;/p&gt;

&lt;p&gt;For Gradle projects using Groovy DSL, add this to &lt;code&gt;build.gradle&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gradle"&gt;&lt;code&gt;&lt;span class="k"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;runtimeOnly&lt;/span&gt; &lt;span class="s1"&gt;'com.mysql:mysql-connector-j'&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Gradle Kotlin DSL (&lt;code&gt;build.gradle.kts&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;runtimeOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.mysql:mysql-connector-j"&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;Use the syntax matching your build file. You don't need both.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Restart Spring Boot
&lt;/h3&gt;

&lt;p&gt;From the project directory, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./mvnw clean spring-boot:run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On Windows PowerShell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;\mvnw.cmd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;clean&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;spring-boot:run&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These commands assume the project includes the Maven Wrapper and Spring Boot Maven plugin.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./gradlew bootRun
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the application connects successfully, its startup log should proceed past DataSource initialization.&lt;/p&gt;

&lt;p&gt;You may see Hikari connection pool initialization or Hibernate startup messages, depending on the project's dependencies.&lt;/p&gt;

&lt;p&gt;If the error changes to &lt;code&gt;Access denied&lt;/code&gt;, &lt;code&gt;Unknown database&lt;/code&gt;, or &lt;code&gt;Communications link failure&lt;/code&gt;, that's useful information. The driver-selection problem may be fixed, and you're now seeing an actual connection problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Spring Boot cannot determine the embedded database driver
&lt;/h2&gt;

&lt;p&gt;The message sounds like MySQL doesn't support the requested database type. That's not what it means.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NONE&lt;/code&gt; is an internal Spring Boot database-type value used in the older error message. It indicates that Spring couldn't identify a supported embedded database during its DataSource configuration.&lt;/p&gt;

&lt;p&gt;Spring Boot can automatically configure databases when it has enough information.&lt;/p&gt;

&lt;p&gt;For an external MySQL database, it needs a valid JDBC URL and a usable driver.&lt;/p&gt;

&lt;p&gt;For an embedded database, it needs an appropriate embedded database dependency, such as H2 or HSQLDB.&lt;/p&gt;

&lt;p&gt;When neither path can be configured correctly, DataSource creation fails.&lt;/p&gt;

&lt;p&gt;This can happen before the application sends a single SQL query to MySQL.&lt;/p&gt;

&lt;p&gt;That's also why changing table definitions, SQL queries, or Hibernate mappings usually won't solve this particular startup error.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cause 1: Missing spring.datasource.url in application.properties
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How to confirm
&lt;/h3&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/main/resources/application.properties
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look for this exact property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;spring.datasource.url&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it's missing, empty, or incorrectly named, Spring Boot may not receive the connection URL.&lt;/p&gt;

&lt;p&gt;For example, this is not a standard Spring Boot DataSource property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;database.url&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;jdbc:mysql://127.0.0.1:3306/appdb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Spring Boot won't automatically treat &lt;code&gt;database.url&lt;/code&gt; as &lt;code&gt;spring.datasource.url&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to fix
&lt;/h3&gt;

&lt;p&gt;Use the expected prefix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;spring.datasource.url&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;jdbc:mysql://127.0.0.1:3306/appdb&lt;/span&gt;
&lt;span class="py"&gt;spring.datasource.username&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;appuser&lt;/span&gt;
&lt;span class="py"&gt;spring.datasource.password&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;your_password&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you prefer YAML, open:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/main/resources/application.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then configure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;spring&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;datasource&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;jdbc:mysql://127.0.0.1:3306/appdb&lt;/span&gt;
    &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;appuser&lt;/span&gt;
    &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;your_password&lt;/span&gt;
    &lt;span class="na"&gt;driver-class-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;com.mysql.cj.jdbc.Driver&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't put these settings under &lt;code&gt;spring.jpa&lt;/code&gt; or &lt;code&gt;spring.hibernate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Those sections handle different database-related configuration.&lt;/p&gt;

&lt;p&gt;Also check the file location. A file accidentally placed under &lt;code&gt;src/main/resources/static&lt;/code&gt; isn't treated as the normal application configuration file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cause 2: MySQL JDBC driver not found in the classpath
&lt;/h2&gt;

&lt;p&gt;A correct database URL doesn't help if the MySQL connector isn't available at runtime.&lt;/p&gt;

&lt;p&gt;Depending on your Spring Boot version and configuration, the application might report:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Failed to determine a suitable driver class
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cannot load driver class: com.mysql.cj.jdbc.Driver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These errors are related, but not identical to the original &lt;code&gt;database type NONE&lt;/code&gt; message.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to confirm
&lt;/h3&gt;

&lt;p&gt;For a Maven project using the current Connector/J artifact, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./mvnw dependency:tree &lt;span class="nt"&gt;-Dincludes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;com.mysql:mysql-connector-j
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should find a dependency similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;com.mysql:mysql-connector-j:jar:...:runtime
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The actual version depends on your project.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./gradlew dependencies &lt;span class="nt"&gt;--configuration&lt;/span&gt; runtimeClasspath
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Search the output for &lt;code&gt;mysql-connector-j&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If the driver isn't listed, check the dependency declaration, dependency exclusions, and build configuration.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to fix
&lt;/h3&gt;

&lt;p&gt;Add the dependency shown in the quick fix, reload the project, and rebuild.&lt;/p&gt;

&lt;p&gt;Older Spring Boot applications may use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;mysql&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;mysql-connector-java&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;runtime&lt;span class="nt"&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the older Maven artifact name. Don't replace it blindly without checking the project's Spring Boot version and dependency management.&lt;/p&gt;

&lt;p&gt;For current MySQL Connector/J releases, the driver class is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;com.mysql.cj.jdbc.Driver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The older class name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;com.mysql.jdbc.Driver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is deprecated in newer Connector/J versions.&lt;/p&gt;

&lt;p&gt;MySQL confirms the current driver name in its &lt;a href="https://dev.mysql.com/doc/connector-j/en/connector-j-reference-driver-name.html" rel="noopener noreferrer"&gt;Connector/J documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My preference is to let Spring Boot manage the connector version whenever possible rather than manually mixing unrelated library versions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cause 3: Spring Boot isn't loading your database profile
&lt;/h2&gt;

&lt;p&gt;This one is easy to miss because the configuration can look perfectly correct.&lt;/p&gt;

&lt;p&gt;Imagine your database settings 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;src/main/resources/application-dev.properties
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;spring.datasource.url&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;jdbc:mysql://127.0.0.1:3306/appdb&lt;/span&gt;
&lt;span class="py"&gt;spring.datasource.username&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;appuser&lt;/span&gt;
&lt;span class="py"&gt;spring.datasource.password&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;your_password&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But you launch the application without activating &lt;code&gt;dev&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Spring Boot might never apply those properties.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to confirm
&lt;/h3&gt;

&lt;p&gt;Check the startup log for a message about active profiles.&lt;/p&gt;

&lt;p&gt;You might see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;No active profile set, falling back to default profiles
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact wording varies across Spring Boot versions.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to fix
&lt;/h3&gt;

&lt;p&gt;Activate your development profile.&lt;/p&gt;

&lt;p&gt;With Maven:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./mvnw spring-boot:run &lt;span class="nt"&gt;-Dspring-boot&lt;/span&gt;.run.profiles&lt;span class="o"&gt;=&lt;/span&gt;dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or set the environment variable on Linux or macOS:&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="nv"&gt;SPRING_PROFILES_ACTIVE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dev ./mvnw spring-boot:run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On Windows PowerShell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;SPRING_PROFILES_ACTIVE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dev"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;\mvnw.cmd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;spring-boot:run&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also set the active profile in the base &lt;code&gt;application.properties&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;spring.profiles.active&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use that only when selecting the profile in application configuration makes sense for your deployment.&lt;/p&gt;

&lt;p&gt;Don't put &lt;code&gt;spring.profiles.active&lt;/code&gt; inside &lt;code&gt;application-dev.properties&lt;/code&gt; on modern Spring Boot versions. Profile activation belongs in a non-profile-specific configuration source.&lt;/p&gt;

&lt;p&gt;One more gotcha: environment variables, command-line arguments, and external configuration files can override packaged configuration.&lt;/p&gt;

&lt;p&gt;A correct setting in your source repository doesn't guarantee that's the value the running application receives.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cause 4: The JDBC URL or MySQL server address is wrong
&lt;/h2&gt;

&lt;p&gt;Once Spring identifies the JDBC driver, the next step is establishing a network connection.&lt;/p&gt;

&lt;p&gt;A typical MySQL JDBC URL looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;spring.datasource.url&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;jdbc:mysql://127.0.0.1:3306/appdb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;jdbc:mysql://&lt;/code&gt; prefix matters.&lt;/p&gt;

&lt;p&gt;This is not a valid MySQL JDBC URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;spring.datasource.url&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;mysql://127.0.0.1:3306/appdb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second format is missing &lt;code&gt;jdbc:&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check that MySQL is reachable
&lt;/h3&gt;

&lt;p&gt;Try connecting directly with the MySQL command-line client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mysql &lt;span class="nt"&gt;-h&lt;/span&gt; 127.0.0.1 &lt;span class="nt"&gt;-P&lt;/span&gt; 3306 &lt;span class="nt"&gt;-u&lt;/span&gt; appuser &lt;span class="nt"&gt;-p&lt;/span&gt; appdb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enter your password when prompted.&lt;/p&gt;

&lt;p&gt;If it works, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should get a result containing &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you receive &lt;code&gt;Access denied&lt;/code&gt;, investigate credentials and MySQL account permissions.&lt;/p&gt;

&lt;p&gt;If you receive &lt;code&gt;Unknown database&lt;/code&gt;, confirm that the named database exists.&lt;/p&gt;

&lt;p&gt;If you receive a connection error, check that MySQL is running and listening on the expected interface and port.&lt;/p&gt;

&lt;p&gt;For another explanation of MySQL host values, see our guide to &lt;a href="https://headsntail.com/blog/mysqli-connect-host-parameter-explained" rel="noopener noreferrer"&gt;the host parameter in mysqli_connect()&lt;/a&gt;. That's the PHP interface, not JDBC, but the server address and connection troubleshooting concepts overlap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; A MySQL connection failure normally produces a different underlying exception from &lt;code&gt;database type NONE&lt;/code&gt;. Don't spend time resetting passwords until Spring Boot can actually select its JDBC driver.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cause 5: Spring Boot tries to configure a database your application doesn't use
&lt;/h2&gt;

&lt;p&gt;Sometimes the application isn't supposed to connect to MySQL at all.&lt;/p&gt;

&lt;p&gt;For example, you create a Spring Boot web service that only handles HTTP requests, but the project includes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.boot&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-boot-starter-data-jpa&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Spring Boot sees database-related dependencies and attempts to configure a DataSource.&lt;/p&gt;

&lt;p&gt;With no JDBC URL or embedded database available, initialization can fail.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to confirm
&lt;/h3&gt;

&lt;p&gt;Check &lt;code&gt;pom.xml&lt;/code&gt; or &lt;code&gt;build.gradle&lt;/code&gt; for dependencies such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spring-boot-starter-data-jpa
spring-boot-starter-jdbc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then check whether your application actually uses JDBC, repositories, JPA entities, or database-backed services.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to fix
&lt;/h3&gt;

&lt;p&gt;If the dependency was added accidentally, remove it.&lt;/p&gt;

&lt;p&gt;If the application genuinely doesn't need a database, you can exclude DataSource auto-configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.example.demo&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.boot.SpringApplication&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.boot.autoconfigure.SpringBootApplication&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@SpringBootApplication&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;exclude&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;DataSourceAutoConfiguration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DemoApplication&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;SpringApplication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DemoApplication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adjust the package and application class to match your project.&lt;/p&gt;

&lt;p&gt;This prevents Spring Boot from automatically creating a DataSource.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't use this as a shortcut in a real MySQL/JPA application.&lt;/strong&gt; Excluding auto-configuration doesn't repair the connection. It may simply replace the original error with missing DataSource, repository, or entity manager errors.&lt;/p&gt;

&lt;p&gt;If you actually want an in-memory database for development or tests, add an appropriate embedded database dependency instead, such as H2:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.h2database&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;h2&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;runtime&lt;span class="nt"&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only do that when an embedded database is intentional. It isn't a substitute for MySQL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cause 6: The app works locally but fails after packaging or deployment
&lt;/h2&gt;

&lt;p&gt;A working IDE launch doesn't prove the deployed application has the same configuration.&lt;/p&gt;

&lt;p&gt;The deployed process may use another active profile, missing environment variables, or a package without the expected JDBC dependency.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check the packaged application
&lt;/h3&gt;

&lt;p&gt;First build the application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./mvnw clean package
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For an executable Spring Boot JAR, inspect its contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jar tf target/your-app.jar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;your-app.jar&lt;/code&gt; with the actual output filename.&lt;/p&gt;

&lt;p&gt;Search the listing for the MySQL connector under the packaged libraries, typically within &lt;code&gt;BOOT-INF/lib&lt;/code&gt; for an executable Spring Boot JAR using that layout.&lt;/p&gt;

&lt;p&gt;Also inspect the packaged configuration under &lt;code&gt;BOOT-INF/classes&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If your project builds a different deployment format, inspect that format instead.&lt;/p&gt;

&lt;p&gt;A clean package can also reveal resource-copying mistakes.&lt;/p&gt;

&lt;p&gt;For example, the source &lt;code&gt;application.properties&lt;/code&gt; might contain a database URL while the copied configuration in &lt;code&gt;target/classes&lt;/code&gt; is empty or outdated.&lt;/p&gt;

&lt;p&gt;A clean rebuild removes stale build output before packaging.&lt;/p&gt;

&lt;p&gt;If MySQL is hosted separately from the application, make sure the JDBC URL uses the hostname reachable from the application's runtime environment. Inside Docker, &lt;code&gt;127.0.0.1&lt;/code&gt; refers to the container itself, not automatically to the host machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  If nothing worked: capture the real Spring Boot failure
&lt;/h2&gt;

&lt;p&gt;At this point, stop changing random properties and collect the first meaningful exception.&lt;/p&gt;

&lt;p&gt;Spring's top-level &lt;code&gt;BeanCreationException&lt;/code&gt; often wraps a more specific failure.&lt;/p&gt;

&lt;p&gt;The useful message is frequently near the bottom of the stack trace, following &lt;code&gt;Caused by:&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enable Spring Boot debug output
&lt;/h3&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./mvnw spring-boot:run &lt;span class="nt"&gt;-Dspring-boot&lt;/span&gt;.run.arguments&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;--debug&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./gradlew bootRun &lt;span class="nt"&gt;--args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'--debug'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Debug mode shows more information about Spring Boot's auto-configuration decisions.&lt;/p&gt;

&lt;p&gt;It can help establish why DataSource auto-configuration was selected and which configuration conditions matched.&lt;/p&gt;

&lt;p&gt;Debug output doesn't automatically print every effective database property.&lt;/p&gt;

&lt;h3&gt;
  
  
  Save the startup log
&lt;/h3&gt;

&lt;p&gt;On Linux or macOS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./mvnw spring-boot:run &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; startup.log 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On Windows PowerShell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;\mvnw.cmd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;spring-boot:run&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;startup.log&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;startup.log&lt;/code&gt; and search for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Caused by:
DataSourceAutoConfiguration
DataSourceProperties
Failed to determine a suitable driver class
Cannot load driver class
Access denied
Communications link failure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Interpret the first relevant root cause rather than treating every nested exception as a separate failure.&lt;/p&gt;

&lt;p&gt;A useful troubleshooting report includes the Spring Boot version, active profile, sanitized JDBC URL, relevant dependency tree, and the first underlying exception.&lt;/p&gt;

&lt;p&gt;Remove passwords, tokens, and other secrets before sharing logs or configuration.&lt;/p&gt;

&lt;p&gt;For comparison, problems such as &lt;a href="https://headsntail.com/blog/laravel-migrate-fresh-seed-table-not-seeding-mysql" rel="noopener noreferrer"&gt;Laravel migrations and MySQL seeding failures&lt;/a&gt; happen at a different stage. If your Spring application never created its DataSource, investigating SQL inserts or table relationships is premature.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why does Spring Boot say database type NONE when I'm using MySQL?
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;NONE&lt;/code&gt; doesn't refer to a MySQL storage engine or database type. It's part of the older Spring Boot error wording used when an embedded database can't be identified during DataSource initialization.&lt;/p&gt;

&lt;p&gt;Check that Spring receives a valid &lt;code&gt;spring.datasource.url&lt;/code&gt; and that the required MySQL driver is available.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is spring.datasource.driver-class-name required for MySQL?
&lt;/h3&gt;

&lt;p&gt;Usually not. Spring Boot can identify the driver from a correctly configured &lt;code&gt;jdbc:mysql://&lt;/code&gt; URL when Connector/J is on the runtime classpath.&lt;/p&gt;

&lt;p&gt;You can explicitly set &lt;code&gt;spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver&lt;/code&gt; while troubleshooting. The setting won't help if the driver library itself is missing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I fix this by adding H2 instead of MySQL Connector/J?
&lt;/h3&gt;

&lt;p&gt;Only if you intend to use H2 as an embedded database. Adding H2 may allow a separate development or test application to start, but it doesn't configure a connection to your MySQL server.&lt;/p&gt;

&lt;p&gt;For a MySQL-backed application, use the MySQL JDBC driver and the correct connection properties.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why does the application work in the IDE but fail with java -jar?
&lt;/h3&gt;

&lt;p&gt;The IDE and packaged application might not load the same profiles, environment variables, dependencies, or configuration files.&lt;/p&gt;

&lt;p&gt;Compare the effective startup settings and inspect the packaged JAR. Don't assume the database driver is included simply because the project compiles successfully.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's the difference between "Cannot determine embedded database driver class" and "Failed to determine a suitable driver class"?
&lt;/h3&gt;

&lt;p&gt;Both errors concern Spring Boot's ability to configure a JDBC DataSource. The first is associated with older Spring Boot error messages, while newer versions commonly report the second.&lt;/p&gt;

&lt;p&gt;The same diagnostic approach applies: check the JDBC URL, available driver, loaded configuration, and active profile before investigating the MySQL server.&lt;/p&gt;

&lt;p&gt;If you're still getting &lt;code&gt;beancreationexception: cannot determine embedded database driver class for database type none&lt;/code&gt;, gather the sanitized startup log and dependency tree, then use &lt;a href="https://headsntail.com/services" rel="noopener noreferrer"&gt;HeadsNTail services&lt;/a&gt; if you need hands-on help identifying the remaining configuration issue.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://headsntail.com/blog/beancreationexception-database-type-none-mysql-fix" rel="noopener noreferrer"&gt;headsntail.com&lt;/a&gt;. Free tools for PHP, Laravel and cPanel work: &lt;a href="https://headsntail.com/tools" rel="noopener noreferrer"&gt;headsntail.com/tools&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>mysql</category>
      <category>database</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Set Variables in a Laravel Blade Template</title>
      <dc:creator>Faizan</dc:creator>
      <pubDate>Sun, 18 Oct 2026 07:29:53 +0000</pubDate>
      <link>https://dev.to/faizan050/how-to-set-variables-in-a-laravel-blade-template-2oag</link>
      <guid>https://dev.to/faizan050/how-to-set-variables-in-a-laravel-blade-template-2oag</guid>
      <description>&lt;p&gt;Need to create a variable inside a Blade template, calculate a value, and display it without getting an &lt;code&gt;Undefined variable&lt;/code&gt; error? You can do it directly in Blade, and you don't need to create a controller just for a simple calculation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Direct answer:&lt;/strong&gt; Use Blade's &lt;code&gt;@php ... @endphp&lt;/code&gt; directive to assign a local PHP variable, then display it with &lt;code&gt;{{ $variable }}&lt;/code&gt;. For values calculated from application data, it's usually better to define them in a controller and pass them to the view. Blade supports normal PHP variables, conditional assignments, arrays, and component properties.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Create a Blade template to reproduce the undefined variable error
&lt;/h2&gt;

&lt;p&gt;Let's use a simple order summary throughout this tutorial.&lt;/p&gt;

&lt;p&gt;We have a product price, a quantity, and a customer name. We want to calculate the total and display it in a Blade view.&lt;/p&gt;

&lt;p&gt;Open your Laravel project's &lt;code&gt;routes/web.php&lt;/code&gt; file and add:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/blade-demo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'blade-demo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'unitPriceCents'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'quantity'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'customerName'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Taylor'&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 create this file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resources/views/blade-demo.blade.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add:&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;!DOCTYPE html&amp;gt;
&amp;lt;html lang="en"&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset="UTF-8"&amp;gt;
    &amp;lt;title&amp;gt;Blade Variables Demo&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;h2&amp;gt;Order Summary&amp;lt;/h2&amp;gt;

    &amp;lt;p&amp;gt;Customer: {{ $customerName }}&amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt;Quantity: {{ $quantity }}&amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt;Total: {{ $subtotal }}&amp;lt;/p&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start the development server from your Laravel project directory:&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 serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://127.0.0.1:8000/blade-demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assuming the server uses its default port, Laravel will throw an exception similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ErrorException
Undefined variable $subtotal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;We passed &lt;code&gt;$unitPriceCents&lt;/code&gt; and &lt;code&gt;$quantity&lt;/code&gt; to the view, but &lt;code&gt;$subtotal&lt;/code&gt; was never defined.&lt;/p&gt;

&lt;p&gt;Blade doesn't automatically calculate missing variables. It compiles templates into PHP, so undefined PHP variables cause the same kind of problem here.&lt;/p&gt;

&lt;p&gt;If your development server can't start, see our guide to &lt;a href="https://headsntail.com/blog/php-artisan-serve-failed-to-listen-127-0-0-1-8000" rel="noopener noreferrer"&gt;fixing php artisan serve when it fails to listen on port 8000&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. How to set variables in a Laravel Blade template using &lt;a class="mentioned-user" href="https://dev.to/php"&gt;@php&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The simplest fix is Laravel's built-in &lt;code&gt;@php&lt;/code&gt; directive.&lt;/p&gt;

&lt;p&gt;Replace your template with:&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;!DOCTYPE html&amp;gt;
&amp;lt;html lang="en"&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset="UTF-8"&amp;gt;
    &amp;lt;title&amp;gt;Blade Variables Demo&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    @php
        $subtotal = $unitPriceCents * $quantity;
    @endphp

    &amp;lt;h2&amp;gt;Order Summary&amp;lt;/h2&amp;gt;

    &amp;lt;p&amp;gt;Customer: {{ $customerName }}&amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt;Quantity: {{ $quantity }}&amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt;Subtotal: ${{ number_format($subtotal / 100, 2) }}&amp;lt;/p&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Refresh the page.&lt;/p&gt;

&lt;p&gt;Expected output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Order Summary

Customer: Taylor
Quantity: 2
Subtotal: $50.00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. You've successfully declared a variable, assigned a value, and displayed it.&lt;/p&gt;

&lt;p&gt;You can assign multiple variables inside the same block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@php
    $subtotal = $unitPriceCents * $quantity;
    $taxRate = 0.10;
    $tax = (int) round($subtotal * $taxRate);
    $total = $subtotal + $tax;
@endphp

&amp;lt;p&amp;gt;Subtotal: ${{ number_format($subtotal / 100, 2) }}&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Tax: ${{ number_format($tax / 100, 2) }}&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Total: ${{ number_format($total / 100, 2) }}&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tax rate here is just an example, not an actual tax rule.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My preference:&lt;/strong&gt; Use &lt;code&gt;@php&lt;/code&gt; for small, display-related calculations. Don't put database queries, payment processing, or complicated business rules inside Blade files.&lt;/p&gt;

&lt;p&gt;The official &lt;a href="https://laravel.com/docs/12.x/blade" rel="noopener noreferrer"&gt;Laravel Blade documentation&lt;/a&gt; documents &lt;code&gt;@php&lt;/code&gt; as the supported way to execute PHP code in a template.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Pass variables from a Laravel controller instead
&lt;/h2&gt;

&lt;p&gt;For real applications, calculating the subtotal outside the template is usually cleaner.&lt;/p&gt;

&lt;p&gt;You don't have to create a controller to demonstrate this. We can move the calculation into our existing route first.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;routes/web.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the demo route with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/blade-demo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$unitPriceCents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2500&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$quantity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nv"&gt;$subtotal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$unitPriceCents&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nv"&gt;$quantity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'blade-demo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'customerName'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Taylor'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'quantity'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$quantity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'subtotal'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$subtotal&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 remove the previous &lt;code&gt;@php&lt;/code&gt; calculation from &lt;code&gt;resources/views/blade-demo.blade.php&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Your view can simply contain:&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;h2&amp;gt;Order Summary&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;Customer: {{ $customerName }}&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Quantity: {{ $quantity }}&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Subtotal: ${{ number_format($subtotal / 100, 2) }}&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This produces the same output, but the calculation happens before Laravel renders the template.&lt;/p&gt;

&lt;p&gt;You can also use PHP's &lt;code&gt;compact()&lt;/code&gt; function:&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;return&lt;/span&gt; &lt;span class="nf"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'blade-demo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;compact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'customerName'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'quantity'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'subtotal'&lt;/span&gt;
&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That version works when all three variables have already been defined.&lt;/p&gt;

&lt;p&gt;In a larger application, the same code would normally live inside a controller method.&lt;/p&gt;

&lt;p&gt;One thing I'd avoid is loading database records from inside a Blade template. If your project has trouble preparing its database, resolve that separately. Our &lt;a href="https://headsntail.com/blog/laravel-migrate-fresh-seed-table-not-seeding-mysql" rel="noopener noreferrer"&gt;Laravel migrate:fresh and seeding troubleshooting guide&lt;/a&gt; covers one common setup issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Set conditional variables and default values in Blade
&lt;/h2&gt;

&lt;p&gt;Sometimes a variable depends on a condition.&lt;/p&gt;

&lt;p&gt;For example, an order may have an optional discount.&lt;/p&gt;

&lt;p&gt;Assuming &lt;code&gt;$subtotal&lt;/code&gt; is already available in the view, add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@php
    $discountCents = $discountCents ?? 0;

    $payableCents = max(0, $subtotal - $discountCents);
@endphp

@if ($discountCents &amp;gt; 0)
    &amp;lt;p&amp;gt;Discount applied&amp;lt;/p&amp;gt;
@else
    &amp;lt;p&amp;gt;No discount applied&amp;lt;/p&amp;gt;
@endif

&amp;lt;p&amp;gt;
    Amount due:
    ${{ number_format($payableCents / 100, 2) }}
&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;??&lt;/code&gt; provides a default value when &lt;code&gt;$discountCents&lt;/code&gt; is missing or &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;max()&lt;/code&gt; call prevents a negative displayed amount if the discount exceeds the subtotal.&lt;/p&gt;

&lt;p&gt;You can also display a default directly:&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;p&amp;gt;Customer: {{ $customerName ?? 'Guest' }}&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or check whether a variable exists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@isset($customerName)
    &amp;lt;p&amp;gt;Welcome, {{ $customerName }}&amp;lt;/p&amp;gt;
@endisset
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A common mistake is trying to use &lt;code&gt;{{ }}&lt;/code&gt; for assignment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{{ $subtotal = 5000 }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PHP can evaluate that assignment, but Blade also prints the result. That's usually not what you want.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;@php&lt;/code&gt; for assignment and &lt;code&gt;{{ }}&lt;/code&gt; for output.&lt;/p&gt;

&lt;p&gt;Also, keep Blade's automatic HTML escaping enabled when displaying user-supplied data. Don't switch to &lt;code&gt;{!! !!}&lt;/code&gt; merely to avoid formatting issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Pass variables to another Blade file using &lt;a class="mentioned-user" href="https://dev.to/include"&gt;@include&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A variable defined in one template can also be passed to an included view.&lt;/p&gt;

&lt;p&gt;Let's move the order total into a reusable partial.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resources/views/partials/order-total.blade.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add:&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;p&amp;gt;
    {{ $label }}:
    ${{ number_format($payableCents / 100, 2) }}
&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your main Blade template, after calculating &lt;code&gt;$payableCents&lt;/code&gt;, replace the previous total paragraph with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@include('partials.order-total', [
    'payableCents' =&amp;gt; $payableCents,
    'label' =&amp;gt; 'Amount due',
])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The partial receives the variables and displays them.&lt;/p&gt;

&lt;p&gt;Expected output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Amount due: $50.00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Blade includes inherit variables available in the parent view, but I prefer passing the important values explicitly. That makes the partial easier to understand and reuse.&lt;/p&gt;

&lt;p&gt;Don't rely on changing a variable inside an included file to update the parent template. Pass the value you need into the partial instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Declare component variables using @props
&lt;/h2&gt;

&lt;p&gt;For reusable UI elements, Blade components are often a better choice than plain includes.&lt;/p&gt;

&lt;p&gt;Create this file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resources/views/components/order-total.blade.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@props([
    'payableCents',
    'label' =&amp;gt; 'Amount due',
])

&amp;lt;div class="order-total"&amp;gt;
    &amp;lt;strong&amp;gt;{{ $label }}&amp;lt;/strong&amp;gt;

    &amp;lt;span&amp;gt;
        ${{ number_format($payableCents / 100, 2) }}
    &amp;lt;/span&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;@props&lt;/code&gt; directive declares which values the component expects.&lt;/p&gt;

&lt;p&gt;Now, in the main template, you can use this component instead of the previous &lt;code&gt;@include&lt;/code&gt;:&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;x-order-total
    :payable-cents="$payableCents"
    label="Final total"
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the colon before &lt;code&gt;payable-cents&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It tells Laravel to evaluate &lt;code&gt;$payableCents&lt;/code&gt; as a PHP expression rather than treating it as literal text.&lt;/p&gt;

&lt;p&gt;Expected result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Final total $50.00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The component's &lt;code&gt;label&lt;/code&gt; property has a default value, so you can omit it if you want.&lt;/p&gt;

&lt;p&gt;For larger Laravel projects, components are useful when the same display logic appears across several pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Fix Blade variables that still show errors
&lt;/h2&gt;

&lt;p&gt;If you've assigned the variable correctly but Laravel still displays an error, check these cases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Undefined variable&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Undefined variable $subtotal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Confirm the variable exists before the template attempts to read it. Check spelling and capitalization, because &lt;code&gt;$subtotal&lt;/code&gt; and &lt;code&gt;$subTotal&lt;/code&gt; are different PHP variables.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trying to use a nonexistent &lt;a class="mentioned-user" href="https://dev.to/set"&gt;@set&lt;/a&gt; directive&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Don't assume this syntax works in a standard Laravel installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@set('subtotal', 5000)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Laravel doesn't provide a built-in &lt;code&gt;@set&lt;/code&gt; directive for this purpose. Some projects register custom directives, but portable Blade templates should use &lt;code&gt;@php&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Changes don't appear after editing Blade&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Try clearing the compiled views:&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 view:clear
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This removes compiled Blade templates so Laravel can compile them again.&lt;/p&gt;

&lt;p&gt;It doesn't clear your application's database or cached business data.&lt;/p&gt;

&lt;p&gt;If you're actually dealing with stored application cache values, that's a different issue. See our &lt;a href="https://headsntail.com/blog/laravel-cache-get-all-items-with-tag" rel="noopener noreferrer"&gt;Laravel cache tag retrieval guide&lt;/a&gt; for an example of working with cache entries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Variable works in one template but not another&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Check where the variable is created and which view receives it. Passing data to a component is different from declaring a local variable in its parent template.&lt;/p&gt;

&lt;p&gt;Don't assume every variable is automatically available across independently rendered components.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verify your Blade variable assignment works
&lt;/h2&gt;

&lt;p&gt;Return to the example and add this code after &lt;code&gt;$subtotal&lt;/code&gt; has been defined:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@php
    $testTotal = $subtotal + 1000;
@endphp

&amp;lt;p&amp;gt;Original: {{ $subtotal }}&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;After adding 1000 cents: {{ $testTotal }}&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://127.0.0.1:8000/blade-demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output with the original example values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Original: 5000
After adding 1000 cents: 6000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If these values appear, the variable assignment is working.&lt;/p&gt;

&lt;p&gt;Remove the test code afterward.&lt;/p&gt;

&lt;p&gt;For support with Blade templates or Laravel application work, you can &lt;a href="https://headsntail.com/contact" rel="noopener noreferrer"&gt;contact HeadsNTail&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Can I declare a variable directly inside a Laravel Blade file?
&lt;/h3&gt;

&lt;p&gt;Yes. Use &lt;code&gt;@php&lt;/code&gt; and &lt;code&gt;@endphp&lt;/code&gt; to declare regular PHP variables inside the template. The variables can then be accessed by subsequent expressions in the same view.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I assign a variable inside a Blade &lt;a class="mentioned-user" href="https://dev.to/if"&gt;@if&lt;/a&gt; statement?
&lt;/h3&gt;

&lt;p&gt;Yes, but it's usually clearer to assign the value before the conditional block. Use &lt;code&gt;@if&lt;/code&gt; to control what gets displayed and &lt;code&gt;@php&lt;/code&gt; when you actually need to store a calculated value.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I give a Blade variable a default value?
&lt;/h3&gt;

&lt;p&gt;Use PHP's null coalescing operator, such as &lt;code&gt;$name = $name ?? 'Guest';&lt;/code&gt;. When you only need a fallback for display, &lt;code&gt;{{ $name ?? 'Guest' }}&lt;/code&gt; is simpler and doesn't require an additional assignment.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I pass a variable from a controller to Blade?
&lt;/h3&gt;

&lt;p&gt;Return a view with an associative array, such as &lt;code&gt;return view('orders.show', ['total' =&amp;gt; $total]);&lt;/code&gt;. Inside &lt;code&gt;resources/views/orders/show.blade.php&lt;/code&gt;, access it using &lt;code&gt;{{ $total }}&lt;/code&gt;. You can also use &lt;code&gt;compact('total')&lt;/code&gt; if that variable exists in the controller method.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is my Blade variable undefined even after using &lt;a class="mentioned-user" href="https://dev.to/php"&gt;@php&lt;/a&gt;?
&lt;/h3&gt;

&lt;p&gt;The assignment may happen after the variable is accessed, or it may be inside a conditional branch that didn't execute. Check variable spelling and whether the correct view receives the data. If the template appears outdated, run &lt;code&gt;php artisan view:clear&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, apply how to set variables in a Laravel Blade template to one real page in your project. Keep display-only calculations in Blade and move data loading or business rules into your application's PHP classes.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://headsntail.com/blog/how-to-set-variables-laravel-blade-template" rel="noopener noreferrer"&gt;headsntail.com&lt;/a&gt;. Free tools for PHP, Laravel and cPanel work: &lt;a href="https://headsntail.com/tools" rel="noopener noreferrer"&gt;headsntail.com/tools&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Find the Query from query_id in MySQL (InnoDB)</title>
      <dc:creator>Faizan</dc:creator>
      <pubDate>Sun, 18 Oct 2026 06:54:52 +0000</pubDate>
      <link>https://dev.to/faizan050/find-the-query-from-queryid-in-mysql-innodb-3p3b</link>
      <guid>https://dev.to/faizan050/find-the-query-from-queryid-in-mysql-innodb-3p3b</guid>
      <description>&lt;p&gt;A MySQL deadlock report shows a query ID, but you can't find the SQL statement that caused the problem. You have the thread ID and query ID from &lt;code&gt;SHOW ENGINE INNODB STATUS&lt;/code&gt;, yet neither tells you directly what was executed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Direct answer:&lt;/strong&gt; To find the query from query_id in mysql, first check whether the SQL statement is still visible in the InnoDB status report or process list. If it has finished, use previously collected Performance Schema history or general query logs. MySQL doesn't provide a standard lookup command that retrieves historical SQL using an InnoDB query ID alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites before investigating the MySQL query ID
&lt;/h2&gt;

&lt;p&gt;You'll need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MySQL 8.0 or 8.4 for the examples below. MariaDB has some differences.&lt;/li&gt;
&lt;li&gt;Access to the MySQL command-line client, MySQL Workbench, or another SQL client.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;PROCESS&lt;/code&gt; privilege to inspect server-wide activity and InnoDB status.&lt;/li&gt;
&lt;li&gt;Appropriate &lt;code&gt;SELECT&lt;/code&gt; privileges for Performance Schema or log tables.&lt;/li&gt;
&lt;li&gt;Administrative privileges if you need to change server logging settings.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The investigation starts with a real kind of InnoDB status entry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MySQL thread id 1106, query id 1360 localhost 127.0.0.1 test2
---TRANSACTION 0 19491, not started, OS thread id 2960035840
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We want to identify the SQL statement associated with query ID &lt;code&gt;1360&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There's an important distinction:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Identifier&lt;/th&gt;
&lt;th&gt;What it represents&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;1106&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;MySQL connection/thread ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;1360&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Server query ID shown by InnoDB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;EVENT_ID&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Performance Schema statement event identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Query_ID&lt;/code&gt; in &lt;code&gt;SHOW PROFILES&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Session profiling identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These identifiers aren't interchangeable.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Find the query from query_id in MySQL InnoDB status
&lt;/h2&gt;

&lt;p&gt;Start by connecting to MySQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mysql &lt;span class="nt"&gt;-u&lt;/span&gt; root &lt;span class="nt"&gt;-p&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the server version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;VERSION&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="o"&gt;@@&lt;/span&gt;&lt;span class="n"&gt;version_comment&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then capture the current InnoDB status:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt; &lt;span class="n"&gt;ENGINE&lt;/span&gt; &lt;span class="n"&gt;INNODB&lt;/span&gt; &lt;span class="n"&gt;STATUS&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="k"&gt;G&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look for these sections:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LATEST DETECTED DEADLOCK
TRANSACTIONS
LIST OF TRANSACTIONS FOR EACH SESSION
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;InnoDB can include the actual SQL statement immediately after the connection and query information.&lt;/p&gt;

&lt;p&gt;For example, you might see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MySQL thread id 1106, query id 1360 localhost root updating
UPDATE orders SET status = 'paid' WHERE id = 25
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In that case, you've found the statement without enabling additional logging.&lt;/p&gt;

&lt;p&gt;But sometimes the output only contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---TRANSACTION 0 19491, not started
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That means the transaction shown isn't currently active. It doesn't provide enough information to reconstruct its previous SQL statements.&lt;/p&gt;

&lt;p&gt;For a saved report on Linux, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mysql &lt;span class="nt"&gt;-u&lt;/span&gt; root &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"SHOW ENGINE INNODB STATUS&lt;/span&gt;&lt;span class="se"&gt;\G&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /tmp/innodb-status.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Search the captured text:&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="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt; 15 &lt;span class="s2"&gt;"query id 1360"&lt;/span&gt; /tmp/innodb-status.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-A 15&lt;/code&gt; option displays 15 lines after the match, where SQL text may appear.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One gotcha:&lt;/strong&gt; &lt;code&gt;SHOW ENGINE INNODB STATUS&lt;/code&gt; is a snapshot, not a complete historical query archive. A newer deadlock can replace the previous deadlock details.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Find the SQL query using the MySQL thread ID
&lt;/h2&gt;

&lt;p&gt;The thread ID is usually more useful than the InnoDB query ID.&lt;/p&gt;

&lt;p&gt;In our example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MySQL thread id 1106
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt; &lt;span class="k"&gt;FULL&lt;/span&gt; &lt;span class="n"&gt;PROCESSLIST&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This displays connected sessions and their current statements.&lt;/p&gt;

&lt;p&gt;You can narrow the search:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;HOST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;COMMAND&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;TIME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;INFO&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;information_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PROCESSLIST&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1106&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="k"&gt;G&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;INFO&lt;/code&gt; column contains the SQL statement currently associated with that connection, when one is available.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;SHOW FULL PROCESSLIST&lt;/code&gt; instead of &lt;code&gt;SHOW PROCESSLIST&lt;/code&gt; if you need the complete statement. The shorter command can truncate the displayed SQL.&lt;/p&gt;

&lt;p&gt;If connection &lt;code&gt;1106&lt;/code&gt; is sleeping, &lt;code&gt;INFO&lt;/code&gt; may be &lt;code&gt;NULL&lt;/code&gt;. If the connection has closed, its row won't appear at all.&lt;/p&gt;

&lt;p&gt;Also, don't confuse the connection ID with the query ID. Searching the process list for &lt;code&gt;1360&lt;/code&gt; instead of &lt;code&gt;1106&lt;/code&gt; could identify an entirely different connection.&lt;/p&gt;

&lt;p&gt;If you're checking which database the application connected to, our guide to the &lt;a href="https://headsntail.com/blog/mysqli-connect-host-parameter-explained" rel="noopener noreferrer"&gt;host parameter in mysqli_connect()&lt;/a&gt; explains how PHP chooses its MySQL server.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Recover recent statements with Performance Schema
&lt;/h2&gt;

&lt;p&gt;Performance Schema is the preferred built-in option for investigating recent statement execution in modern MySQL.&lt;/p&gt;

&lt;p&gt;Check whether it's enabled:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt; &lt;span class="n"&gt;VARIABLES&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'performance_schema'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the value is &lt;code&gt;ON&lt;/code&gt;, inspect the statement consumers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ENABLED&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;performance_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setup_consumers&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;NAME&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'events_statements%'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To inspect the current statement for connection &lt;code&gt;1106&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PROCESSLIST_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EVENT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EVENT_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SQL_TEXT&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;performance_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;threads&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;performance_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;events_statements_current&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
    &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;THREAD_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;THREAD_ID&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PROCESSLIST_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1106&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="k"&gt;G&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For recently completed statements, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PROCESSLIST_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EVENT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SQL_TEXT&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;performance_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;threads&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;performance_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;events_statements_history&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
    &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;THREAD_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;THREAD_ID&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PROCESSLIST_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1106&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EVENT_ID&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives you recent SQL associated with the connection, provided the events were recorded and haven't been discarded.&lt;/p&gt;

&lt;p&gt;For a larger, server-wide history, enable its consumer before reproducing the problem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;performance_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setup_instruments&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;ENABLED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'YES'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TIMED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'YES'&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;NAME&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'statement/%'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;performance_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setup_consumers&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;ENABLED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'YES'&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;NAME&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'events_statements_current'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'events_statements_history_long'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then examine recent captured statements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;THREAD_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;EVENT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;SQL_TEXT&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;performance_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;events_statements_history_long&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;SQL_TEXT&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;THREAD_ID&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;EVENT_ID&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a known live connection, filter these events by joining to &lt;code&gt;performance_schema.threads&lt;/code&gt;, as shown earlier.&lt;/p&gt;

&lt;p&gt;There are limitations. Performance Schema history has finite capacity, SQL text may be truncated, and a connection that has already closed might no longer have a thread mapping.&lt;/p&gt;

&lt;p&gt;Its &lt;code&gt;EVENT_ID&lt;/code&gt; is also not the InnoDB query ID &lt;code&gt;1360&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;See the &lt;a href="https://dev.mysql.com/doc/refman/8.4/en/performance-schema-statement-tables.html" rel="noopener noreferrer"&gt;MySQL Performance Schema documentation&lt;/a&gt; for the supported statement-history tables.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Enable the MySQL general query log to capture future queries
&lt;/h2&gt;

&lt;p&gt;If the query has already disappeared, the general query log is often the most practical way to investigate a reproducible problem.&lt;/p&gt;

&lt;p&gt;The log records statements received by MySQL together with their connection identifiers.&lt;/p&gt;

&lt;p&gt;First, save the existing settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;VARIABLES&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;Variable_name&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'general_log'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'log_output'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For temporary troubleshooting, enable table logging:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;log_output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'TABLE'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;general_log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ON'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;log_output&lt;/code&gt; was previously &lt;code&gt;FILE&lt;/code&gt; and you need to preserve file logging, use &lt;code&gt;FILE,TABLE&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;Now reproduce the application problem.&lt;/p&gt;

&lt;p&gt;Search for statements belonging to connection &lt;code&gt;1106&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;command_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;CONVERT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="k"&gt;USING&lt;/span&gt; &lt;span class="n"&gt;utf8mb4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;sql_text&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;general_log&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;thread_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1106&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;command_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Query'&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;event_time&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output shows the statements received on that connection after logging was enabled.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This doesn't mean the general log stores query ID &lt;code&gt;1360&lt;/code&gt;.&lt;/strong&gt; It stores the connection ID, timestamp, command type, and statement text. You'll correlate the relevant statement using the thread ID and time of the problem.&lt;/p&gt;

&lt;p&gt;General logging can generate substantial data and expose sensitive application values. I'd enable it only for a short diagnostic window, preferably outside peak traffic.&lt;/p&gt;

&lt;p&gt;If the investigation exposes an incorrect SQL expression, our &lt;a href="https://headsntail.com/blog/select-multiple-columns-based-on-condition-sql" rel="noopener noreferrer"&gt;guide to selecting multiple columns based on SQL conditions&lt;/a&gt; covers a related part of checking query logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Keep MySQL statement history enabled after restart
&lt;/h2&gt;

&lt;p&gt;Runtime changes to Performance Schema consumers don't necessarily survive a server restart.&lt;/p&gt;

&lt;p&gt;For a Linux MySQL installation using the Debian or Ubuntu package layout, a common configuration path is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/etc/mysql/mysql.conf.d/mysqld.cnf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other installations may use &lt;code&gt;/etc/my.cnf&lt;/code&gt; or another configuration file.&lt;/p&gt;

&lt;p&gt;To keep the extended statement-history consumer enabled, add these settings under &lt;code&gt;[mysqld]&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[mysqld]&lt;/span&gt;
&lt;span class="py"&gt;performance_schema&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;ON&lt;/span&gt;
&lt;span class="py"&gt;performance-schema-consumer-events-statements-history-long&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;ON&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the server requires these changes, restart MySQL during an approved maintenance window:&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="nb"&gt;sudo &lt;/span&gt;systemctl restart mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then verify the configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ENABLED&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;performance_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setup_consumers&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'events_statements_history_long'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The expected value is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;events_statements_history_long | YES
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This captures future completed statements. It cannot restore query history that was never recorded.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verify that query capture works
&lt;/h2&gt;

&lt;p&gt;After enabling monitoring, execute a harmless statement from an application connection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;CONNECTION_ID&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="mi"&gt;12345&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;query_capture_test&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep the connection open.&lt;/p&gt;

&lt;p&gt;From another administrative connection, inspect the history:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PROCESSLIST_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EVENT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SQL_TEXT&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;performance_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;threads&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;performance_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;events_statements_history_long&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
    &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;THREAD_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;THREAD_ID&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SQL_TEXT&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="s1"&gt;'%query_capture_test%'&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EVENT_ID&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should find the test statement if the consumer is collecting events and the row hasn't been discarded.&lt;/p&gt;

&lt;p&gt;For general logging, search &lt;code&gt;mysql.general_log&lt;/code&gt; using the connection ID returned by &lt;code&gt;CONNECTION_ID()&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common errors during setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Access denied when reading Performance Schema
&lt;/h3&gt;

&lt;p&gt;Your MySQL account may lack the necessary permissions.&lt;/p&gt;

&lt;p&gt;Check your grants:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt; &lt;span class="n"&gt;GRANTS&lt;/span&gt; &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;CURRENT_USER&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ask the database administrator for the required read access. Avoid granting broad administrative permissions to application accounts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unknown column 'QUERY_ID' in Performance Schema
&lt;/h3&gt;

&lt;p&gt;MySQL's statement event tables use &lt;code&gt;THREAD_ID&lt;/code&gt; and &lt;code&gt;EVENT_ID&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;They don't provide an InnoDB &lt;code&gt;QUERY_ID&lt;/code&gt; column.&lt;/p&gt;

&lt;p&gt;Don't try:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;performance_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;events_statements_history_long&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;QUERY_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1360&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead, use the thread mapping and statement history demonstrated above.&lt;/p&gt;

&lt;h3&gt;
  
  
  No rows returned from statement history
&lt;/h3&gt;

&lt;p&gt;Check that the required consumers are enabled and that the statements were executed after monitoring started.&lt;/p&gt;

&lt;p&gt;History can also be overwritten on a busy server. &lt;code&gt;events_statements_history_long&lt;/code&gt; isn't permanent storage.&lt;/p&gt;

&lt;h3&gt;
  
  
  MariaDB query IDs behave differently
&lt;/h3&gt;

&lt;p&gt;MariaDB exposes a &lt;code&gt;QUERY_ID&lt;/code&gt; column in &lt;code&gt;information_schema.PROCESSLIST&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For a still-running query, you can try:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;QUERY_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;INFO&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;information_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PROCESSLIST&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;QUERY_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1360&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 MariaDB-specific and only helps while the relevant process-list entry remains available.&lt;/p&gt;

&lt;p&gt;Don't assume MySQL and MariaDB expose identical diagnostic columns, even if both are accessed using the &lt;code&gt;mysql&lt;/code&gt; command-line client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rollback: disable temporary query logging
&lt;/h2&gt;

&lt;p&gt;Once you've captured enough evidence, turn off general query logging if you enabled it solely for troubleshooting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;general_log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;OFF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restore the original &lt;code&gt;log_output&lt;/code&gt; value you recorded before making changes.&lt;/p&gt;

&lt;p&gt;For example, only if the previous value was &lt;code&gt;FILE&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;GLOBAL&lt;/span&gt; &lt;span class="n"&gt;log_output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'FILE'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If general logging was already enabled before your investigation, restore that original state instead of leaving it disabled.&lt;/p&gt;

&lt;p&gt;Also revert temporary Performance Schema instrumentation and consumer changes to their recorded previous values.&lt;/p&gt;

&lt;p&gt;For persistent changes, remove only the settings you added to the MySQL configuration and restart during maintenance.&lt;/p&gt;

&lt;p&gt;Don't truncate or delete diagnostic logs until you've saved the evidence you need.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Can I get the exact SQL statement using only a MySQL query ID?
&lt;/h3&gt;

&lt;p&gt;Not reliably. An InnoDB query ID isn't a persistent lookup key for SQL history. You'll need the original status output, an active connection, or previously captured statement logs to identify the query.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the difference between thread ID and query ID in MySQL?
&lt;/h3&gt;

&lt;p&gt;The thread ID identifies a MySQL connection. The query ID identifies a query execution in the server's diagnostic context. One connection can execute many statements, so the values represent different things.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does SHOW PROFILES display the same query ID as InnoDB?
&lt;/h3&gt;

&lt;p&gt;No. &lt;code&gt;SHOW PROFILES&lt;/code&gt; uses session profiling IDs, which aren't the same as the query IDs printed by InnoDB. The profiling statements are also deprecated in MySQL, so Performance Schema is the better choice for new monitoring setups.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I find a query after the MySQL connection has closed?
&lt;/h3&gt;

&lt;p&gt;Only if the statement was captured somewhere that still retains it, such as the general query log or suitable diagnostic history. A closed connection disappears from the process list, and Performance Schema history isn't guaranteed to survive long enough for later investigation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can MySQL automatically save SQL statements involved in deadlocks?
&lt;/h3&gt;

&lt;p&gt;MySQL can record InnoDB deadlock information, including SQL statements available at the time. For ongoing deadlock investigation, &lt;code&gt;innodb_print_all_deadlocks&lt;/code&gt; can send details of all detected InnoDB deadlocks to the MySQL error log rather than relying only on the most recent deadlock shown by &lt;code&gt;SHOW ENGINE INNODB STATUS&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you need hands-on help configuring query diagnostics, you can &lt;a href="https://headsntail.com/contact" rel="noopener noreferrer"&gt;contact HeadsNTail&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The practical next step when you need to find the query from query_id in mysql is to capture the InnoDB report, record the connection ID, and enable short-term SQL logging before reproducing the issue.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://headsntail.com/blog/find-query-from-query-id-mysql" rel="noopener noreferrer"&gt;headsntail.com&lt;/a&gt;. Free tools for PHP, Laravel and cPanel work: &lt;a href="https://headsntail.com/tools" rel="noopener noreferrer"&gt;headsntail.com/tools&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>mysql</category>
      <category>database</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to select multiple columns based on a condition in SQL?</title>
      <dc:creator>Faizan</dc:creator>
      <pubDate>Sat, 17 Oct 2026 13:08:34 +0000</pubDate>
      <link>https://dev.to/faizan050/how-to-select-multiple-columns-based-on-a-condition-in-sql-3e5j</link>
      <guid>https://dev.to/faizan050/how-to-select-multiple-columns-based-on-a-condition-in-sql-3e5j</guid>
      <description>&lt;p&gt;ERROR 1241 (21000): Operand should contain 1 column(s).&lt;/p&gt;

&lt;p&gt;This error often appears when you try to make a SQL &lt;code&gt;CASE&lt;/code&gt; expression return multiple columns at once. If you're asking "how to select multiple columns based on a condition in sql?", the first thing to understand is the difference between filtering rows and changing which column values appear in your results. Both are possible, but they require different SQL techniques.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick answer:&lt;/strong&gt; To select multiple columns based on a condition, list the required columns in &lt;code&gt;SELECT&lt;/code&gt; and filter matching rows using &lt;code&gt;WHERE&lt;/code&gt;. If individual column values should change depending on a condition, use separate &lt;code&gt;CASE&lt;/code&gt; expressions for each output column. If the actual number or names of returned columns must change, use separate queries or safely constructed dynamic SQL.&lt;/p&gt;

&lt;p&gt;Here's how to implement each approach in MySQL without running into confusing syntax errors.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Create a sample table to understand conditional column selection
&lt;/h2&gt;

&lt;p&gt;We'll use an employee table throughout this tutorial.&lt;/p&gt;

&lt;p&gt;Imagine you're building an employee management dashboard. Your database stores employee names, departments, salaries, and employment status.&lt;/p&gt;

&lt;p&gt;You want to answer questions such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Show the names and salaries of active sales employees.&lt;/li&gt;
&lt;li&gt;Display different salary columns depending on the department.&lt;/li&gt;
&lt;li&gt;Return salary totals for active and inactive employees.&lt;/li&gt;
&lt;li&gt;Change the columns displayed when someone selects a different report.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Start by creating a temporary table.&lt;/p&gt;

&lt;p&gt;Open MySQL Workbench, phpMyAdmin, or your preferred MySQL client and execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;TEMPORARY&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;demo_employees&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TEMPORARY&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;demo_employees&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;employee_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;full_name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;annual_salary&lt;/span&gt; &lt;span class="nb"&gt;DECIMAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now insert some sample records:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;demo_employees&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;employee_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;annual_salary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt;
    &lt;span class="p"&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;'Ana'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Sales'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;54000&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Ben'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Support'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;47000&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Cara'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Sales'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;62000&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'inactive'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Deepak'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Engineering'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;78000&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Ema'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Sales'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;51000&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Farah'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Support'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50000&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'inactive'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Confirm that the records exist:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;demo_employees&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;employee_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see six employees across three departments.&lt;/p&gt;

&lt;p&gt;We're using a temporary table so the exercise doesn't modify an existing application table. &lt;strong&gt;Run all the SQL examples using the same database connection&lt;/strong&gt;, because MySQL temporary tables disappear when their connection closes.&lt;/p&gt;

&lt;p&gt;If you're testing through PHP and the connection fails before your query runs, check the &lt;a href="https://headsntail.com/blog/mysqli-connect-host-parameter-explained" rel="noopener noreferrer"&gt;mysqli_connect host parameter explained&lt;/a&gt;. Connection problems and SQL syntax problems need different fixes.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Select multiple columns using a WHERE condition
&lt;/h2&gt;

&lt;p&gt;This is the simplest solution, and it's usually all you need.&lt;/p&gt;

&lt;p&gt;Suppose your dashboard should show only active employees from the Sales department.&lt;/p&gt;

&lt;p&gt;You need three output columns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Employee ID&lt;/li&gt;
&lt;li&gt;Employee name&lt;/li&gt;
&lt;li&gt;Annual salary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The condition belongs in &lt;code&gt;WHERE&lt;/code&gt;, not inside the column list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;employee_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;annual_salary&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;demo_employees&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Sales'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;employee_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected result:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;employee_id&lt;/th&gt;
&lt;th&gt;full_name&lt;/th&gt;
&lt;th&gt;annual_salary&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Ana&lt;/td&gt;
&lt;td&gt;54000.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Ema&lt;/td&gt;
&lt;td&gt;51000.00&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Notice what SQL does here.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SELECT&lt;/code&gt; decides which columns appear in the result.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;WHERE&lt;/code&gt; decides which rows qualify.&lt;/p&gt;

&lt;p&gt;These are independent parts of the query. You can return five columns while filtering by a sixth column, even if that sixth column isn't displayed.&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 sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;employee_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;annual_salary&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;demo_employees&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The query filters using &lt;code&gt;status&lt;/code&gt;, but doesn't include &lt;code&gt;status&lt;/code&gt; in the returned columns.&lt;/p&gt;

&lt;p&gt;That's perfectly valid.&lt;/p&gt;

&lt;h3&gt;
  
  
  Select columns using multiple conditions
&lt;/h3&gt;

&lt;p&gt;You can combine conditions with &lt;code&gt;AND&lt;/code&gt;, &lt;code&gt;OR&lt;/code&gt;, or &lt;code&gt;IN&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For employees belonging to either Sales or Support:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;employee_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;department&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;demo_employees&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Sales'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Support'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;employee_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected employee IDs: &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt;, and &lt;code&gt;5&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You could write the same department condition using &lt;code&gt;OR&lt;/code&gt;, but &lt;code&gt;IN&lt;/code&gt; is easier to read when you're checking one column against several values.&lt;/p&gt;

&lt;p&gt;One mistake I frequently recommend checking for is missing parentheses when mixing &lt;code&gt;AND&lt;/code&gt; and &lt;code&gt;OR&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This query may return unexpected results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;employee_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;department&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;demo_employees&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Sales'&lt;/span&gt;
   &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Support'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SQL evaluates &lt;code&gt;AND&lt;/code&gt; before &lt;code&gt;OR&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So inactive Sales employees can still appear.&lt;/p&gt;

&lt;p&gt;If you want active employees from either department, write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;employee_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;department&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;demo_employees&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Sales'&lt;/span&gt;
       &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Support'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Better still, use the earlier &lt;code&gt;IN&lt;/code&gt; example.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. How to select multiple columns based on a condition in SQL?
&lt;/h2&gt;

&lt;p&gt;Sometimes filtering rows isn't the real requirement.&lt;/p&gt;

&lt;p&gt;You want to return every employee, but show different values depending on their department.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Sales employees should have their salary in &lt;code&gt;sales_salary&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Support employees should have their salary in &lt;code&gt;support_salary&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Everyone else should have &lt;code&gt;NULL&lt;/code&gt; in those columns.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where &lt;code&gt;CASE&lt;/code&gt; becomes useful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use a separate CASE expression for each column
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;employee_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="k"&gt;CASE&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Sales'&lt;/span&gt;
        &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="n"&gt;annual_salary&lt;/span&gt;
        &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
    &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;sales_salary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="k"&gt;CASE&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Support'&lt;/span&gt;
        &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="n"&gt;annual_salary&lt;/span&gt;
        &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
    &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;support_salary&lt;/span&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;demo_employees&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;employee_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected result:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;employee_id&lt;/th&gt;
&lt;th&gt;full_name&lt;/th&gt;
&lt;th&gt;sales_salary&lt;/th&gt;
&lt;th&gt;support_salary&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Ana&lt;/td&gt;
&lt;td&gt;54000.00&lt;/td&gt;
&lt;td&gt;NULL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Ben&lt;/td&gt;
&lt;td&gt;NULL&lt;/td&gt;
&lt;td&gt;47000.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Cara&lt;/td&gt;
&lt;td&gt;62000.00&lt;/td&gt;
&lt;td&gt;NULL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Deepak&lt;/td&gt;
&lt;td&gt;NULL&lt;/td&gt;
&lt;td&gt;NULL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Ema&lt;/td&gt;
&lt;td&gt;51000.00&lt;/td&gt;
&lt;td&gt;NULL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Farah&lt;/td&gt;
&lt;td&gt;NULL&lt;/td&gt;
&lt;td&gt;50000.00&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All six employees appear because there's no &lt;code&gt;WHERE&lt;/code&gt; condition.&lt;/p&gt;

&lt;p&gt;However, each calculated column displays a salary only when its condition matches.&lt;/p&gt;

&lt;p&gt;There's an important detail here: Cara and Farah are inactive, but their salaries still appear because these conditions only check the department.&lt;/p&gt;

&lt;p&gt;If inactive employees shouldn't have a salary displayed, extend each condition.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;employee_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="k"&gt;CASE&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Sales'&lt;/span&gt;
         &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;
        &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="n"&gt;annual_salary&lt;/span&gt;
        &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
    &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;sales_salary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="k"&gt;CASE&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Support'&lt;/span&gt;
         &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;
        &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="n"&gt;annual_salary&lt;/span&gt;
        &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
    &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;support_salary&lt;/span&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;demo_employees&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;employee_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now inactive employees receive &lt;code&gt;NULL&lt;/code&gt; in both salary columns.&lt;/p&gt;

&lt;p&gt;Keep in mind that conditional display isn't a security control. Database permissions and application authorization must still protect sensitive salary data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why one CASE cannot return two columns
&lt;/h3&gt;

&lt;p&gt;Here's a common incorrect attempt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;employee_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="k"&gt;CASE&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Sales'&lt;/span&gt;
        &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;annual_salary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;department&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;details&lt;/span&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;demo_employees&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This produces an error similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ERROR 1241 (21000): Operand should contain 1 column(s)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem isn't the condition.&lt;/p&gt;

&lt;p&gt;It's the attempt to return two values from a single &lt;code&gt;CASE&lt;/code&gt; expression.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;CASE&lt;/code&gt; expression produces one result value. It doesn't expand into multiple output columns.&lt;/p&gt;

&lt;p&gt;The correct approach is to use separate expressions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;employee_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="k"&gt;CASE&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Sales'&lt;/span&gt;
        &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="n"&gt;full_name&lt;/span&gt;
        &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt;
    &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;display_label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="k"&gt;CASE&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Sales'&lt;/span&gt;
        &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="n"&gt;annual_salary&lt;/span&gt;
        &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
    &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;display_salary&lt;/span&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;demo_employees&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each &lt;code&gt;CASE&lt;/code&gt; produces one column.&lt;/p&gt;

&lt;p&gt;You can also use MySQL's &lt;code&gt;IF()&lt;/code&gt; function for simpler conditions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;employee_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;IF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Sales'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;annual_salary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;NULL&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;sales_salary&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;demo_employees&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;IF()&lt;/code&gt; works for a basic true-or-false decision.&lt;/p&gt;

&lt;p&gt;I prefer &lt;code&gt;CASE&lt;/code&gt; when several conditions are involved because it's easier to extend and is also standard SQL.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://dev.mysql.com/doc/refman/8.4/en/flow-control-functions.html" rel="noopener noreferrer"&gt;MySQL documentation for CASE expressions&lt;/a&gt; explains the supported syntax.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Select multiple columns with different WHERE conditions
&lt;/h2&gt;

&lt;p&gt;Another situation is filtering rows based on different combinations of column values.&lt;/p&gt;

&lt;p&gt;Suppose the business rule is:&lt;/p&gt;

&lt;p&gt;Return active Sales employees, plus Support employees whose annual salary is at least 50000.&lt;/p&gt;

&lt;p&gt;The query is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;employee_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;department&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;annual_salary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;demo_employees&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Sales'&lt;/span&gt;
     &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;OR&lt;/span&gt;

    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Support'&lt;/span&gt;
     &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;annual_salary&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;50000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;employee_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected matching employees:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;employee_id&lt;/th&gt;
&lt;th&gt;full_name&lt;/th&gt;
&lt;th&gt;department&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Ana&lt;/td&gt;
&lt;td&gt;Sales&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Ema&lt;/td&gt;
&lt;td&gt;Sales&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Farah&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Farah appears even though her status is inactive.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because the Support condition checks the salary, not the employment status.&lt;/p&gt;

&lt;p&gt;This is intentional for the example, but it's exactly the kind of mistake that can cause incorrect reports in a real application.&lt;/p&gt;

&lt;p&gt;If both groups must be active, apply the active condition to the entire expression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;employee_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;department&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;annual_salary&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;demo_employees&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Sales'&lt;/span&gt;
        &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Support'&lt;/span&gt;
            &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;annual_salary&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;50000&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;employee_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now Farah is excluded.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't confuse WHERE with CASE
&lt;/h3&gt;

&lt;p&gt;The distinction is simple.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;WHERE&lt;/code&gt; when a condition should remove entire rows.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;CASE&lt;/code&gt; when a condition should change a value in the returned row.&lt;/p&gt;

&lt;p&gt;You can combine both:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;employee_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="k"&gt;CASE&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;annual_salary&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;60000&lt;/span&gt;
        &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="s1"&gt;'High salary'&lt;/span&gt;
        &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="s1"&gt;'Standard salary'&lt;/span&gt;
    &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;salary_category&lt;/span&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;demo_employees&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;employee_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only active employees appear, and each employee receives a calculated salary category.&lt;/p&gt;

&lt;p&gt;This pattern is useful for administrative dashboards and filtered reports.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Select conditional totals across multiple columns
&lt;/h2&gt;

&lt;p&gt;Sometimes you don't need individual employee records.&lt;/p&gt;

&lt;p&gt;You want a report containing several calculated columns based on conditions.&lt;/p&gt;

&lt;p&gt;For example, show each department with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Total number of employees.&lt;/li&gt;
&lt;li&gt;Number of active employees.&lt;/li&gt;
&lt;li&gt;Number of inactive employees.&lt;/li&gt;
&lt;li&gt;Combined salary of active employees.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can build this using &lt;strong&gt;conditional aggregation&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;department&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;total_employees&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;CASE&lt;/span&gt;
            &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;
            &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="k"&gt;END&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;active_employees&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;CASE&lt;/span&gt;
            &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'inactive'&lt;/span&gt;
            &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="k"&gt;END&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;inactive_employees&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;CASE&lt;/span&gt;
            &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;
            &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="n"&gt;annual_salary&lt;/span&gt;
            &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="k"&gt;END&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;active_salary_total&lt;/span&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;demo_employees&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected result:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;department&lt;/th&gt;
&lt;th&gt;total_employees&lt;/th&gt;
&lt;th&gt;active_employees&lt;/th&gt;
&lt;th&gt;inactive_employees&lt;/th&gt;
&lt;th&gt;active_salary_total&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Engineering&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;78000.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sales&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;105000.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;47000.00&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Here's how this works.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GROUP BY department&lt;/code&gt; creates one result row for each department.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;COUNT(*)&lt;/code&gt; counts all employees in that department.&lt;/p&gt;

&lt;p&gt;Each &lt;code&gt;SUM(CASE ...)&lt;/code&gt; evaluates a condition for individual rows and adds the matching values.&lt;/p&gt;

&lt;p&gt;For the active employee count:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;CASE&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;
        &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;END&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A matching employee contributes &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A non-matching employee contributes &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For the salary total, the same approach adds salary amounts instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why WHERE can break conditional totals
&lt;/h3&gt;

&lt;p&gt;Don't add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to the aggregation query if you still need inactive employee counts.&lt;/p&gt;

&lt;p&gt;That condition removes inactive rows before the grouping and aggregation happen.&lt;/p&gt;

&lt;p&gt;Your inactive count would always be zero.&lt;/p&gt;

&lt;p&gt;Keep both types of records available and let the individual &lt;code&gt;CASE&lt;/code&gt; expressions handle the conditions.&lt;/p&gt;

&lt;p&gt;There's another small detail.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;ELSE 0&lt;/code&gt; makes the total zero when a department has no matching employees. Without &lt;code&gt;ELSE&lt;/code&gt;, the expression returns &lt;code&gt;NULL&lt;/code&gt; for non-matching records, and &lt;code&gt;SUM()&lt;/code&gt; may return &lt;code&gt;NULL&lt;/code&gt; if every input is &lt;code&gt;NULL&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That difference matters when your result feeds a chart or financial report.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Select different column names dynamically in MySQL
&lt;/h2&gt;

&lt;p&gt;What if your requirement is more specific?&lt;/p&gt;

&lt;p&gt;You want the SQL query itself to return different columns depending on a selected report.&lt;/p&gt;

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

&lt;p&gt;Directory report:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;employee_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;department&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;demo_employees&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Payroll report:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;employee_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;annual_salary&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;demo_employees&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These queries have different output structures.&lt;/p&gt;

&lt;p&gt;A normal &lt;code&gt;CASE&lt;/code&gt; expression cannot switch the entire &lt;code&gt;SELECT&lt;/code&gt; column list.&lt;/p&gt;

&lt;p&gt;You need separate SQL statements or dynamic SQL.&lt;/p&gt;

&lt;h3&gt;
  
  
  Build a safe dynamic SELECT statement
&lt;/h3&gt;

&lt;p&gt;MySQL supports prepared statements using &lt;code&gt;PREPARE&lt;/code&gt; and &lt;code&gt;EXECUTE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For this example, we'll allow only predefined column lists.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="k"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'payroll'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;CASE&lt;/span&gt;
    &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="k"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'payroll'&lt;/span&gt;
        &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="s1"&gt;'employee_id, full_name, annual_salary'&lt;/span&gt;

    &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="k"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'directory'&lt;/span&gt;
        &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="s1"&gt;'employee_id, full_name, department'&lt;/span&gt;

    &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="s1"&gt;'employee_id, full_name'&lt;/span&gt;
&lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="k"&gt;sql&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CONCAT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'SELECT '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;' FROM demo_employees'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;' WHERE status = ?'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;' ORDER BY employee_id'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;PREPARE&lt;/span&gt; &lt;span class="n"&gt;employee_stmt&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="k"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;EXECUTE&lt;/span&gt; &lt;span class="n"&gt;employee_stmt&lt;/span&gt; &lt;span class="k"&gt;USING&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;DEALLOCATE&lt;/span&gt; &lt;span class="k"&gt;PREPARE&lt;/span&gt; &lt;span class="n"&gt;employee_stmt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;@view = 'payroll'&lt;/code&gt;, the result contains employee IDs, names, and salaries.&lt;/p&gt;

&lt;p&gt;Change the variable to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="k"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'directory'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then rerun the remaining statements.&lt;/p&gt;

&lt;p&gt;You'll receive employee IDs, names, and departments instead.&lt;/p&gt;

&lt;p&gt;This works because the complete SQL statement is built before MySQL prepares it.&lt;/p&gt;

&lt;p&gt;The column list is selected from fixed, trusted alternatives.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Never concatenate an unchecked user-supplied column name directly into SQL.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Prepared statement placeholders such as &lt;code&gt;?&lt;/code&gt; work for values, not SQL identifiers or entire column lists.&lt;/p&gt;

&lt;p&gt;If users can choose columns, map their choices to a list of permitted identifiers first.&lt;/p&gt;

&lt;p&gt;For most applications, I would keep a small set of predefined queries rather than construct complicated SQL strings. It's easier to review and much harder to misuse.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Apply conditional column selection in Laravel
&lt;/h2&gt;

&lt;p&gt;If you're using Laravel, the Query Builder makes ordinary column selection straightforward.&lt;/p&gt;

&lt;p&gt;Suppose your actual database contains a permanent &lt;code&gt;employees&lt;/code&gt; table with the columns used in our example.&lt;/p&gt;

&lt;p&gt;To get active Sales employees:&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="no"&gt;Illuminate\Support\Facades\DB&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$employees&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'employees'&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;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'employee_id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'full_name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'annual_salary'&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;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'department'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Sales'&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;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'status'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'active'&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;orderBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'employee_id'&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;get&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 Laravel equivalent of our second step.&lt;/p&gt;

&lt;h3&gt;
  
  
  Choose different columns for different reports
&lt;/h3&gt;

&lt;p&gt;You can select the column list in PHP before building the query.&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="no"&gt;Illuminate\Support\Facades\DB&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$reportType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'payroll'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$allowedColumns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'directory'&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;'employee_id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'full_name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'department'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s1"&gt;'payroll'&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;'employee_id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'full_name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'annual_salary'&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="nv"&gt;$columns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$allowedColumns&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$reportType&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nv"&gt;$allowedColumns&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'directory'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nv"&gt;$employees&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'employees'&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;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$columns&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;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'status'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'active'&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;orderBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'employee_id'&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;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part is the &lt;code&gt;$allowedColumns&lt;/code&gt; mapping.&lt;/p&gt;

&lt;p&gt;Your application chooses a known column list rather than accepting arbitrary SQL identifiers from a request.&lt;/p&gt;

&lt;p&gt;For calculated columns, Laravel can also use raw SQL expressions with bound values.&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="no"&gt;Illuminate\Support\Facades\DB&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Sales'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$employees&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'employees'&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;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'employee_id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'full_name'&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;selectRaw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'CASE
            WHEN department = ?
            THEN annual_salary
            ELSE NULL
         END AS selected_salary'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$department&lt;/span&gt;&lt;span class="p"&gt;]&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;orderBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'employee_id'&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;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, Laravel binds the department value safely.&lt;/p&gt;

&lt;p&gt;Don't interpolate untrusted values directly into &lt;code&gt;selectRaw()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And remember that the earlier &lt;code&gt;demo_employees&lt;/code&gt; table was temporary. The Laravel examples assume you've created a normal application table with the corresponding fields.&lt;/p&gt;

&lt;h3&gt;
  
  
  What if the columns come from different tables?
&lt;/h3&gt;

&lt;p&gt;That's a different problem.&lt;/p&gt;

&lt;p&gt;Suppose names are stored in &lt;code&gt;employees&lt;/code&gt;, but salaries are stored in &lt;code&gt;employee_salaries&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You'll need a &lt;code&gt;JOIN&lt;/code&gt; to combine those records.&lt;/p&gt;

&lt;p&gt;For a related example, see &lt;a href="https://headsntail.com/blog/codeigniter-query-builder-join-existing-select" rel="noopener noreferrer"&gt;how to JOIN a second table in CodeIgniter Query Builder&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The principle is the same in Laravel or plain MySQL: a join combines related tables, while &lt;code&gt;WHERE&lt;/code&gt; and &lt;code&gt;CASE&lt;/code&gt; handle the conditions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verify the results before using the query in production
&lt;/h2&gt;

&lt;p&gt;Before adding your final SQL to a controller or report, check the row counts and the actual result values.&lt;/p&gt;

&lt;p&gt;Start with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;department&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;employee_count&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;demo_employees&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells you how many records exist for each department and status combination.&lt;/p&gt;

&lt;p&gt;Now test the basic filter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;matching_employees&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;demo_employees&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Sales'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected result:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Next, check a conditional calculation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;CASE&lt;/span&gt;
            &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Sales'&lt;/span&gt;
             &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;
            &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="k"&gt;END&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;active_sales_count&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;demo_employees&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected result:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Both methods should agree.&lt;/p&gt;

&lt;p&gt;If they don't, inspect the conditions rather than immediately changing the SQL structure.&lt;/p&gt;

&lt;p&gt;I'd also check these issues before blaming &lt;code&gt;CASE&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;NULL comparisons:&lt;/strong&gt; Use &lt;code&gt;IS NULL&lt;/code&gt; and &lt;code&gt;IS NOT NULL&lt;/code&gt;, not &lt;code&gt;= NULL&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unexpected duplicate rows:&lt;/strong&gt; Look for joins that match multiple records.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Incorrect data types:&lt;/strong&gt; Confirm that the values being compared use compatible types.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Missing columns:&lt;/strong&gt; Run &lt;code&gt;SHOW COLUMNS FROM demo_employees;&lt;/code&gt; to inspect the table.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Incorrect column aliases:&lt;/strong&gt; An alias defined in &lt;code&gt;SELECT&lt;/code&gt; generally cannot be referenced directly in the same query's &lt;code&gt;WHERE&lt;/code&gt; clause.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a query runs but returns zero records, temporarily remove the &lt;code&gt;WHERE&lt;/code&gt; clause and add conditions back one at a time.&lt;/p&gt;

&lt;p&gt;That's usually more useful than rewriting the whole query.&lt;/p&gt;

&lt;p&gt;If the query is slow on a large production table, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;EXPLAIN&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;employee_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;annual_salary&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;demo_employees&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Sales'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;EXPLAIN&lt;/code&gt; shows how MySQL plans to read the table.&lt;/p&gt;

&lt;p&gt;For a real, persistent table, check whether indexes support your frequently used filters. Don't automatically add an index for every column, because indexes also cost storage and make writes more expensive.&lt;/p&gt;

&lt;p&gt;For a second set of eyes on a production query, you can also check &lt;a href="https://headsntail.com/services" rel="noopener noreferrer"&gt;HeadsNTail services&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Can I select multiple columns using one CASE statement in SQL?
&lt;/h3&gt;

&lt;p&gt;Not using a single &lt;code&gt;CASE&lt;/code&gt; expression in a normal &lt;code&gt;SELECT&lt;/code&gt; list. Each &lt;code&gt;CASE&lt;/code&gt; expression produces one result value, so you'll need a separate expression for every conditional output column. If you want to change the actual set of output columns, use separate queries or dynamic SQL.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I select multiple columns with multiple WHERE conditions?
&lt;/h3&gt;

&lt;p&gt;List the columns after &lt;code&gt;SELECT&lt;/code&gt;, then combine your filters using &lt;code&gt;AND&lt;/code&gt;, &lt;code&gt;OR&lt;/code&gt;, or &lt;code&gt;IN&lt;/code&gt;. Use parentheses to make the intended logic clear when mixing &lt;code&gt;AND&lt;/code&gt; and &lt;code&gt;OR&lt;/code&gt;. Remember that &lt;code&gt;WHERE&lt;/code&gt; filters rows, not individual column values.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's the difference between CASE and IF in MySQL?
&lt;/h3&gt;

&lt;p&gt;Both allow conditional values to be returned in a query. &lt;code&gt;IF()&lt;/code&gt; takes a condition and two possible results, while &lt;code&gt;CASE&lt;/code&gt; can express multiple conditions more clearly. &lt;code&gt;CASE&lt;/code&gt; is standard SQL, making it a better choice when portability matters.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can SQL dynamically select column names based on user input?
&lt;/h3&gt;

&lt;p&gt;Yes, but the column list must be decided before the SQL statement is prepared and executed. You can choose between predefined queries in your application or construct a statement using validated identifiers. Parameter placeholders cannot replace column names.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I use WHERE and CASE together in the same SELECT query?
&lt;/h3&gt;

&lt;p&gt;Yes. &lt;code&gt;WHERE&lt;/code&gt; removes rows that don't match your filter, while &lt;code&gt;CASE&lt;/code&gt; calculates conditional values for rows that remain. Using both is common in reporting queries where you need to filter employees and calculate different output values based on their departments or statuses.&lt;/p&gt;

&lt;p&gt;Next, apply these patterns to a small copy of your real data. Once you understand the difference between filtering rows, calculating conditional values, and switching column lists, the question "how to select multiple columns based on a condition in sql?" becomes much easier to solve.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://headsntail.com/blog/select-multiple-columns-based-on-condition-sql" rel="noopener noreferrer"&gt;headsntail.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>mysql</category>
      <category>database</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>What Is the Host Parameter in mysqli_connect()?</title>
      <dc:creator>Faizan</dc:creator>
      <pubDate>Sat, 17 Oct 2026 12:40:11 +0000</pubDate>
      <link>https://dev.to/faizan050/what-is-the-host-parameter-in-mysqliconnect-2n7m</link>
      <guid>https://dev.to/faizan050/what-is-the-host-parameter-in-mysqliconnect-2n7m</guid>
      <description>&lt;p&gt;HNT-START&lt;br&gt;
TITLE: What Is the Host Parameter in mysqli_connect()?&lt;br&gt;
SLUG: mysqli-connect-host-parameter-explained&lt;br&gt;
EXCERPT: Learn what the host parameter means in mysqli_connect(), when to use localhost or an IP address, and how to fix common MySQL connection errors.&lt;/p&gt;
&lt;h2&gt;
  
  
  CATEGORY: MySQL
&lt;/h2&gt;

&lt;p&gt;You'll know exactly which host value to use in &lt;code&gt;mysqli_connect()&lt;/code&gt; after a few minutes of checking your PHP and MySQL setup. The &lt;strong&gt;host parameter&lt;/strong&gt; is the first argument of &lt;code&gt;mysqli_connect()&lt;/code&gt;, and it tells PHP where to find the MySQL database server. If you're asking "what is the host parameter? what value should i put as the first argument in mysqli_connect()?", the answer depends on whether MySQL runs on your computer, another server, or inside a container.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick answer:&lt;/strong&gt; Use &lt;code&gt;localhost&lt;/code&gt; when PHP and MySQL run on the same machine. Use &lt;code&gt;127.0.0.1&lt;/code&gt; when you specifically want to connect to local MySQL over TCP/IP. If your database runs on another server, enter its actual hostname or IP address. Don't use your website domain unless it also points to the MySQL server.&lt;/p&gt;

&lt;p&gt;The confusion usually starts with a simple PHP 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="nv"&gt;$conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;mysqli_connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'root'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'my_database'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Someone copies this connection from a tutorial, changes the database name, and expects it to work everywhere.&lt;/p&gt;

&lt;p&gt;It might work on XAMPP. It might fail immediately on shared hosting or inside Docker.&lt;/p&gt;

&lt;p&gt;The reason isn't complicated. &lt;code&gt;localhost&lt;/code&gt; describes where the database server is relative to PHP, not where your website is accessible from a browser.&lt;/p&gt;

&lt;p&gt;We'll use a small order management application with a database called &lt;code&gt;orders_db&lt;/code&gt; to explain how the connection works and how to fix it when the hostname is wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the host parameter works in mysqli_connect()
&lt;/h2&gt;

&lt;p&gt;The syntax of &lt;code&gt;mysqli_connect()&lt;/code&gt; is:&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="nb"&gt;mysqli_connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;$hostname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;$database&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;$port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;$socket&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each parameter has a specific purpose.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Host&lt;/td&gt;
&lt;td&gt;Location of the MySQL server&lt;/td&gt;
&lt;td&gt;&lt;code&gt;localhost&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Username&lt;/td&gt;
&lt;td&gt;MySQL account&lt;/td&gt;
&lt;td&gt;&lt;code&gt;app_user&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Password&lt;/td&gt;
&lt;td&gt;MySQL account password&lt;/td&gt;
&lt;td&gt;Your actual password&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;Database to select&lt;/td&gt;
&lt;td&gt;&lt;code&gt;orders_db&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Port&lt;/td&gt;
&lt;td&gt;TCP port number&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3306&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Socket&lt;/td&gt;
&lt;td&gt;Local socket path, when needed&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/var/run/mysqld/mysqld.sock&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The port and socket arguments are optional.&lt;/p&gt;

&lt;p&gt;The first argument tells PHP where it should try to establish the database connection.&lt;/p&gt;

&lt;p&gt;The second and third arguments are used to authenticate with MySQL. The fourth selects the database your application wants to work with.&lt;/p&gt;

&lt;p&gt;Think of the connection process like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PHP application
      |
      | mysqli_connect()
      |
      v
MySQL host
(localhost or remote server)
      |
      v
MySQL authentication
(username + password)
      |
      v
Database: orders_db
      |
      v
Execute SQL queries
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For our order management application, a normal connection might be:&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="nv"&gt;$conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;mysqli_connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'127.0.0.1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'app_user'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'your_password'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'orders_db'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mi"&gt;3306&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This assumes the database exists, the MySQL user has been created, and the user has permission to access it.&lt;/p&gt;

&lt;p&gt;Here, PHP connects to the local machine over TCP/IP using port &lt;code&gt;3306&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It doesn't search for a database named &lt;code&gt;127.0.0.1&lt;/code&gt;. That value identifies the server, not the database.&lt;/p&gt;

&lt;h3&gt;
  
  
  A complete PHP MySQL connection example
&lt;/h3&gt;

&lt;p&gt;Create a file called &lt;code&gt;db.php&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="nb"&gt;mysqli_report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="no"&gt;MYSQLI_REPORT_ERROR&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="no"&gt;MYSQLI_REPORT_STRICT&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'127.0.0.1'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'app_user'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'your_actual_password'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$database&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'orders_db'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3306&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nv"&gt;$conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;mysqli_connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nv"&gt;$database&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nv"&gt;$port&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;mysqli_set_charset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'utf8mb4'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'MySQL connection successful'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;mysqli_close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$conn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mysqli_sql_exception&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nb"&gt;error_log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'Database connection failed: '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt;
        &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getMessage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nb"&gt;http_response_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Unable to connect to the database.'&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;Replace the example username and password with your actual credentials.&lt;/p&gt;

&lt;p&gt;If the database connection succeeds, you'll see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MySQL connection successful
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the connection fails, the script logs the technical error rather than exposing sensitive information to website visitors.&lt;/p&gt;

&lt;p&gt;That's the approach I'd use for diagnosing a connection in a real application.&lt;/p&gt;

&lt;p&gt;For production, keep credentials in environment configuration outside the public web directory. Don't leave real database passwords inside publicly accessible diagnostic files.&lt;/p&gt;

&lt;p&gt;Also, don't assume changing &lt;code&gt;$host&lt;/code&gt; will fix every connection error. The hostname, authentication credentials, database name, and server configuration are separate things.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the host parameter? What value should I put as the first argument in mysqli_connect()?
&lt;/h2&gt;

&lt;p&gt;The correct value depends on where your PHP application runs and where the MySQL server runs.&lt;/p&gt;

&lt;p&gt;Here's the practical comparison:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Your setup&lt;/th&gt;
&lt;th&gt;Host value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PHP and MySQL on the same computer&lt;/td&gt;
&lt;td&gt;&lt;code&gt;localhost&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Local MySQL connection over TCP/IP&lt;/td&gt;
&lt;td&gt;&lt;code&gt;127.0.0.1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database on a separate server&lt;/td&gt;
&lt;td&gt;Actual database hostname or IP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PHP and MySQL in separate Docker Compose services&lt;/td&gt;
&lt;td&gt;MySQL service name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shared hosting&lt;/td&gt;
&lt;td&gt;Hostname supplied by hosting provider&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud-managed MySQL&lt;/td&gt;
&lt;td&gt;Database endpoint supplied by provider&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The important part is choosing a value based on your actual environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use localhost for a local PHP and MySQL installation
&lt;/h3&gt;

&lt;p&gt;Suppose you're running Apache, PHP, and MySQL through XAMPP on Windows.&lt;/p&gt;

&lt;p&gt;Both PHP and MySQL are installed on the same computer.&lt;/p&gt;

&lt;p&gt;A connection can use:&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;$host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your code might look like:&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="nv"&gt;$conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;mysqli_connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'app_user'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'your_password'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'orders_db'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this setup, &lt;code&gt;localhost&lt;/code&gt; is appropriate because the MySQL server is running locally.&lt;/p&gt;

&lt;p&gt;You don't need to enter your computer's public IP address.&lt;/p&gt;

&lt;p&gt;You also don't need to enter the URL you type into Chrome to open your PHP application.&lt;/p&gt;

&lt;p&gt;One thing to check: XAMPP installations don't all have the same MySQL credentials.&lt;/p&gt;

&lt;p&gt;Some fresh development installations may have a &lt;code&gt;root&lt;/code&gt; account without a password. Others have been configured differently.&lt;/p&gt;

&lt;p&gt;Don't assume the username is always &lt;code&gt;root&lt;/code&gt;, and don't copy an empty root password into a production application.&lt;/p&gt;

&lt;p&gt;A dedicated MySQL user is the safer choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use 127.0.0.1 to connect through TCP/IP
&lt;/h3&gt;

&lt;p&gt;You might wonder why PHP examples sometimes use:&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;$host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;while others use:&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;$host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'127.0.0.1'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both refer to the local machine, but they don't always use the same connection method.&lt;/p&gt;

&lt;p&gt;On Linux and other Unix-like systems, MySQL clients normally use a Unix socket when the hostname is &lt;code&gt;localhost&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When you use &lt;code&gt;127.0.0.1&lt;/code&gt;, the client connects over TCP/IP.&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="nv"&gt;$conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;mysqli_connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'127.0.0.1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'app_user'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'your_password'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'orders_db'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mi"&gt;3306&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This explicitly requests a TCP connection to the local machine on port &lt;code&gt;3306&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That difference matters when PHP can't find the MySQL socket file.&lt;/p&gt;

&lt;p&gt;For example, you might get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysqli_sql_exception: No such file or directory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If PHP is using a local Unix socket and the configured socket path is incorrect, switching to &lt;code&gt;127.0.0.1&lt;/code&gt; may work.&lt;/p&gt;

&lt;p&gt;However, MySQL must be listening on TCP/IP, and the account must have permission to connect.&lt;/p&gt;

&lt;p&gt;Changing the host doesn't start a stopped MySQL server or fix an incorrect password.&lt;/p&gt;

&lt;p&gt;One gotcha: on Unix-like systems, passing a TCP port alongside &lt;code&gt;localhost&lt;/code&gt; doesn't necessarily force TCP. If you need TCP explicitly, use &lt;code&gt;127.0.0.1&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use the actual database server address for remote MySQL
&lt;/h3&gt;

&lt;p&gt;Now suppose your PHP application runs on one server and MySQL runs on another.&lt;/p&gt;

&lt;p&gt;Your website might be available at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://app.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the MySQL server might use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.internal.example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your connection should look like:&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="nv"&gt;$conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;mysqli_connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'db.internal.example'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'app_user'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'your_password'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'orders_db'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mi"&gt;3306&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The hostname above is illustrative. Replace it with your actual database endpoint.&lt;/p&gt;

&lt;p&gt;If the hosting provider gives you an IP address, you can use that instead.&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="nv"&gt;$host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'192.0.2.10'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That address belongs to a reserved documentation range. It isn't a real database server for this example.&lt;/p&gt;

&lt;p&gt;A remote MySQL server must also accept connections from your application.&lt;/p&gt;

&lt;p&gt;This may involve MySQL account permissions, firewall settings, and secure network access.&lt;/p&gt;

&lt;p&gt;Don't open MySQL to the entire public internet just to make a PHP connection work.&lt;/p&gt;

&lt;p&gt;Where possible, use private networking and appropriate encryption for remote database connections.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where you'll meet the host parameter in real PHP projects
&lt;/h2&gt;

&lt;p&gt;The MySQL host setting appears in more places than the &lt;code&gt;mysqli_connect()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;You'll find it in local development tools, shared hosting, Docker, Laravel, and server configuration files.&lt;/p&gt;

&lt;h3&gt;
  
  
  XAMPP and WAMP
&lt;/h3&gt;

&lt;p&gt;For XAMPP or WAMP, the most common starting point is:&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;$host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the connection doesn't work, open the XAMPP or WAMP control panel.&lt;/p&gt;

&lt;p&gt;Check whether the database service is running.&lt;/p&gt;

&lt;p&gt;Then confirm the configured port.&lt;/p&gt;

&lt;p&gt;For example, if MySQL is using port &lt;code&gt;3307&lt;/code&gt;, your code must specify that port when connecting over TCP:&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="nv"&gt;$conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;mysqli_connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'127.0.0.1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'app_user'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'your_password'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'orders_db'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mi"&gt;3307&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A wrong port can produce a connection error even when your hostname is correct.&lt;/p&gt;

&lt;p&gt;I'd check the service status and port before reinstalling MySQL or editing random configuration files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Shared hosting and cPanel
&lt;/h3&gt;

&lt;p&gt;On shared hosting, the database might run on the same server as PHP or on a separate database server.&lt;/p&gt;

&lt;p&gt;Open your hosting control panel and find the MySQL connection details.&lt;/p&gt;

&lt;p&gt;The host may be:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Or it may be a hostname provided by your hosting company.&lt;/p&gt;

&lt;p&gt;Don't assume your website domain is also the database hostname.&lt;/p&gt;

&lt;p&gt;Similarly, the address used to access phpMyAdmin is not necessarily the address that your PHP application should use for MySQL.&lt;/p&gt;

&lt;p&gt;If your hosting company gives you a database hostname, use that value.&lt;/p&gt;

&lt;h3&gt;
  
  
  Docker Compose
&lt;/h3&gt;

&lt;p&gt;Docker is one of the easiest places to get &lt;code&gt;localhost&lt;/code&gt; wrong.&lt;/p&gt;

&lt;p&gt;Imagine PHP running inside one container and MySQL running inside another.&lt;/p&gt;

&lt;p&gt;From inside the PHP container, &lt;code&gt;localhost&lt;/code&gt; refers to the PHP container itself.&lt;/p&gt;

&lt;p&gt;It doesn't automatically refer to the MySQL container.&lt;/p&gt;

&lt;p&gt;Consider this Compose configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mysql&lt;/span&gt;

  &lt;span class="na"&gt;mysql&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql:8.4&lt;/span&gt;

    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_DATABASE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;orders_db&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app_user&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;change_this_password&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;change_this_root_password&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is an example configuration, assuming the application Dockerfile exists.&lt;/p&gt;

&lt;p&gt;The example passwords must be replaced with suitable credentials or secret management before deployment.&lt;/p&gt;

&lt;p&gt;Because the database service is named &lt;code&gt;mysql&lt;/code&gt;, the PHP application running inside the &lt;code&gt;app&lt;/code&gt; service can usually use:&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;$host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'mysql'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Docker Compose provides name resolution between services sharing its network.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;127.0.0.1&lt;/code&gt; inside the PHP container would point to the PHP container, not the MySQL container.&lt;/p&gt;

&lt;p&gt;Also, &lt;code&gt;depends_on&lt;/code&gt; doesn't guarantee that MySQL is ready to accept connections. Applications may need a database health check or connection retry.&lt;/p&gt;

&lt;p&gt;If PHP runs directly on the Windows or Linux host rather than inside Compose, the connection setup is different. You may need a published database port.&lt;/p&gt;

&lt;h3&gt;
  
  
  Laravel DB_HOST configuration
&lt;/h3&gt;

&lt;p&gt;Laravel uses the same underlying concept, although it normally connects through PDO instead of calling &lt;code&gt;mysqli_connect()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In Laravel, you'll usually configure the host in &lt;code&gt;.env&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=orders_db
DB_USERNAME=app_user
DB_PASSWORD=your_password
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;DB_HOST&lt;/code&gt; value tells Laravel where MySQL is located.&lt;/p&gt;

&lt;p&gt;If the database moves to another machine, the host value may need to change.&lt;/p&gt;

&lt;p&gt;After updating Laravel environment configuration, cached settings may need to be cleared:&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;If your deployment uses configuration caching, rebuild the cache according to your deployment process.&lt;/p&gt;

&lt;p&gt;For a related database setup problem, read &lt;a href="https://headsntail.com/blog/laravel-migrate-fresh-seed-table-not-seeding-mysql" rel="noopener noreferrer"&gt;Why php artisan migrate:fresh --seed can't seed a MySQL table&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common misunderstandings about MySQL connection errors
&lt;/h2&gt;

&lt;p&gt;Developers sometimes change the hostname whenever a MySQL connection fails.&lt;/p&gt;

&lt;p&gt;That can make troubleshooting harder because different errors point to different problems.&lt;/p&gt;

&lt;p&gt;Read the actual exception first.&lt;/p&gt;

&lt;h3&gt;
  
  
  mysqli_connect(): Connection refused
&lt;/h3&gt;

&lt;p&gt;A failed connection might report:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysqli_sql_exception: Connection refused
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On Windows, you may see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;No connection could be made because the target machine actively refused it
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This usually means the requested network endpoint isn't accepting the connection.&lt;/p&gt;

&lt;p&gt;Possible causes include a stopped MySQL service, an incorrect port, or a server listening on a different network interface.&lt;/p&gt;

&lt;p&gt;Test the connection outside PHP.&lt;/p&gt;

&lt;p&gt;If you have the MySQL command-line client installed, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mysql &lt;span class="nt"&gt;--protocol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;TCP &lt;span class="nt"&gt;--host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;127.0.0.1 &lt;span class="nt"&gt;--port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3306 &lt;span class="nt"&gt;--user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;app_user &lt;span class="nt"&gt;--password&lt;/span&gt; orders_db
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The client will prompt for the password.&lt;/p&gt;

&lt;p&gt;If the command fails, investigate the MySQL service and network settings.&lt;/p&gt;

&lt;p&gt;If the command succeeds but PHP fails, compare the exact host, port, and credentials.&lt;/p&gt;

&lt;p&gt;On Windows, you can also test TCP connectivity through PowerShell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Test-NetConnection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;127.0.0.1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Port&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;3306&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TcpTestSucceeded : True
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This confirms that a TCP connection can be established to that endpoint.&lt;/p&gt;

&lt;p&gt;It doesn't confirm MySQL authentication or database permissions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Access denied for user 'root'@'localhost'
&lt;/h3&gt;

&lt;p&gt;Another common error looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Access denied for user 'root'@'localhost'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means the MySQL server rejected the account during authentication or authorization.&lt;/p&gt;

&lt;p&gt;It doesn't automatically mean the database hostname is wrong.&lt;/p&gt;

&lt;p&gt;Check the username and password first.&lt;/p&gt;

&lt;p&gt;MySQL accounts are identified by both username and client host information.&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 sql"&gt;&lt;code&gt;&lt;span class="s1"&gt;'app_user'&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="s1"&gt;'app_user'&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="s1"&gt;'192.0.2.%'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;can have different authentication settings and permissions.&lt;/p&gt;

&lt;p&gt;The second address pattern is illustrative.&lt;/p&gt;

&lt;p&gt;A detail that causes confusion is that the host part of a MySQL account describes where an account is permitted to connect from. It isn't necessarily the hostname PHP uses to find the database server.&lt;/p&gt;

&lt;p&gt;Don't fix an access-denied error by granting unrestricted database access to every host.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unknown database 'orders_db'
&lt;/h3&gt;

&lt;p&gt;Suppose PHP reports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Unknown database 'orders_db'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This indicates that the requested database wasn't found on the MySQL server that received the connection.&lt;/p&gt;

&lt;p&gt;Check the database name.&lt;/p&gt;

&lt;p&gt;If you're connecting to a remote server, also verify you're reaching the correct MySQL instance.&lt;/p&gt;

&lt;p&gt;Changing:&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;$host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&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 php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'127.0.0.1'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;won't create a missing database.&lt;/p&gt;

&lt;h3&gt;
  
  
  No such file or directory
&lt;/h3&gt;

&lt;p&gt;On Unix-like systems, you may encounter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysqli_sql_exception: No such file or directory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A common cause is an incorrect local MySQL socket path.&lt;/p&gt;

&lt;p&gt;For example, PHP might be trying to access a socket file that doesn't exist at the configured location.&lt;/p&gt;

&lt;p&gt;Try connecting over TCP:&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;$host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'127.0.0.1'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If that works, investigate the socket configuration.&lt;/p&gt;

&lt;p&gt;If TCP also fails, check the MySQL service and listening interfaces.&lt;/p&gt;

&lt;h3&gt;
  
  
  mysql_connect() is not mysqli_connect()
&lt;/h3&gt;

&lt;p&gt;Some old PHP tutorials contain:&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="nb"&gt;mysql_connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'root'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;''&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That function belonged to the old &lt;code&gt;mysql&lt;/code&gt; extension, which was removed from PHP.&lt;/p&gt;

&lt;p&gt;Modern PHP applications should use MySQLi or PDO.&lt;/p&gt;

&lt;p&gt;If you're maintaining older code, see &lt;a href="https://headsntail.com/blog/mysql-fetch-array-expects-resource-fix" rel="noopener noreferrer"&gt;How to fix mysql_fetch_array() expects parameter 1 to be resource&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to check which MySQL server PHP connected to
&lt;/h2&gt;

&lt;p&gt;Sometimes your connection succeeds, but you're unsure whether PHP is using the intended database server.&lt;/p&gt;

&lt;p&gt;For example, your development and production databases might have similar names.&lt;/p&gt;

&lt;p&gt;You can ask MySQL which server and database you're using.&lt;/p&gt;

&lt;p&gt;After establishing a working &lt;code&gt;$conn&lt;/code&gt; connection, run:&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="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mysqli_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;$conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"SELECT
        DATABASE() AS database_name,
        @@hostname AS server_hostname,
        @@port AS server_port"&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mysqli_fetch_assoc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;pre&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nb"&gt;print_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$row&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;/pre&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The query reports the currently selected database, the MySQL server's configured hostname, and its configured port.&lt;/p&gt;

&lt;p&gt;Example output format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Array
(
    [database_name] =&amp;gt; orders_db
    [server_hostname] =&amp;gt; database-server
    [server_port] =&amp;gt; 3306
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The actual hostname and port depend on your environment.&lt;/p&gt;

&lt;p&gt;This is useful when you suspect PHP is connecting to the wrong database instance.&lt;/p&gt;

&lt;p&gt;Run the diagnostic only in a trusted environment. Remove or protect the output before deploying publicly.&lt;/p&gt;

&lt;p&gt;You can find the formal argument definitions in the &lt;a href="https://www.php.net/manual/en/mysqli.construct.php" rel="noopener noreferrer"&gt;official PHP mysqli_connect() documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  When the MySQL host parameter matters and when it doesn't
&lt;/h2&gt;

&lt;p&gt;The host parameter matters whenever PHP must establish a database connection.&lt;/p&gt;

&lt;p&gt;It becomes particularly relevant when moving a website between servers, connecting to remote MySQL, configuring Docker networks, or changing the database service port.&lt;/p&gt;

&lt;p&gt;It also matters when switching between a local Unix socket and a TCP/IP connection.&lt;/p&gt;

&lt;p&gt;However, the host parameter doesn't control SQL syntax or the structure of your database.&lt;/p&gt;

&lt;p&gt;Consider this query:&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="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mysqli_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;$conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'SELECT unknown_column FROM orders'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the &lt;code&gt;unknown_column&lt;/code&gt; field doesn't exist, MySQL will report an SQL error.&lt;/p&gt;

&lt;p&gt;Changing the host won't repair that query.&lt;/p&gt;

&lt;p&gt;The same applies to missing tables, incorrect column names, data type mismatches, and invalid SQL statements.&lt;/p&gt;

&lt;p&gt;A successful database connection proves only that PHP could reach the MySQL server, authenticate, and select the requested database.&lt;/p&gt;

&lt;p&gt;It doesn't prove that every SQL query in the application will work.&lt;/p&gt;

&lt;p&gt;I'd avoid changing connection settings once you've verified that the application reaches the correct server.&lt;/p&gt;

&lt;p&gt;If a query is failing, inspect the query and the actual database schema instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is the default host value in mysqli_connect()?
&lt;/h3&gt;

&lt;p&gt;PHP's MySQLi connection function can use a configured default hostname when the argument is omitted. In many development environments, this corresponds to &lt;code&gt;localhost&lt;/code&gt;. It's better to specify the intended hostname explicitly so the connection doesn't depend on environment-specific defaults.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should I use localhost or 127.0.0.1 for MySQL?
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;localhost&lt;/code&gt; for a normal local connection when your configuration supports it. Use &lt;code&gt;127.0.0.1&lt;/code&gt; if you specifically need a local TCP/IP connection. On Linux, the distinction is particularly relevant because &lt;code&gt;localhost&lt;/code&gt; normally selects a Unix socket.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I use an IP address as the first argument in mysqli_connect()?
&lt;/h3&gt;

&lt;p&gt;Yes. The first argument accepts a hostname or IP address. &lt;code&gt;127.0.0.1&lt;/code&gt; identifies the local loopback interface, while a reachable remote address can identify a database running on another machine.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the default MySQL port for mysqli_connect()?
&lt;/h3&gt;

&lt;p&gt;MySQL commonly listens on TCP port &lt;code&gt;3306&lt;/code&gt;. Your server may use a different port, depending on its configuration. You can provide the required TCP port as the fifth argument of &lt;code&gt;mysqli_connect()&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why does mysqli_connect() work on localhost but fail on hosting?
&lt;/h3&gt;

&lt;p&gt;Your hosting server may have a different MySQL hostname, username, password, port, or access policy. Check the database connection details provided by your hosting company. Also verify that the PHP server can reach the database and that the MySQL account has permission to connect.&lt;/p&gt;

&lt;p&gt;If you're still asking "what is the host parameter? what value should i put as the first argument in mysqli_connect()?", start by identifying where MySQL actually runs. Test that hostname and port with the MySQL command-line client, then use the verified connection details in your PHP application.&lt;br&gt;
HNT-END&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://headsntail.com/blog/mysqli-connect-host-parameter-explained" rel="noopener noreferrer"&gt;headsntail.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>mysql</category>
      <category>database</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Export Large Data With Chunk in Laravel-Excel: Fix</title>
      <dc:creator>Faizan</dc:creator>
      <pubDate>Sat, 17 Oct 2026 12:12:24 +0000</pubDate>
      <link>https://dev.to/faizan050/export-large-data-with-chunk-in-laravel-excel-fix-4pka</link>
      <guid>https://dev.to/faizan050/export-large-data-with-chunk-in-laravel-excel-fix-4pka</guid>
      <description>&lt;p&gt;The most common mistake developers make when exporting thousands of database records is loading every row into memory before generating the Excel file. Calling &lt;code&gt;Model::all()&lt;/code&gt; or &lt;code&gt;Model::get()&lt;/code&gt; inside an export may work perfectly during development, then fail when the production database grows.&lt;/p&gt;

&lt;p&gt;If you need to &lt;strong&gt;export large data with chunk in laravel-excel&lt;/strong&gt;, the fix is usually to stop building a full collection and let Laravel Excel retrieve database records in smaller batches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick answer:&lt;/strong&gt; Use Laravel Excel's &lt;code&gt;FromQuery&lt;/code&gt; concern instead of &lt;code&gt;FromCollection&lt;/code&gt; with &lt;code&gt;Model::all()&lt;/code&gt; or &lt;code&gt;Model::get()&lt;/code&gt;. Return an Eloquent query without executing it. Laravel Excel processes the query in chunks automatically. For larger exports, queue the operation so it runs outside the HTTP request and avoids browser timeouts.&lt;/p&gt;

&lt;p&gt;This guide uses one example throughout: exporting customer orders to an Excel spreadsheet. We'll start with the memory-heavy approach, replace it with a chunked query, and then move the export into Laravel's queue system.&lt;/p&gt;

&lt;p&gt;The implementation follows the Laravel Excel 3.1 API. If you're using another major version, check the corresponding documentation before copying the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Reproduce the memory problem with a large Laravel export
&lt;/h2&gt;

&lt;p&gt;Imagine an order management application containing a growing number of customer orders.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;orders&lt;/code&gt; table has these columns:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Column&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Order identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;order_number&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Reference number&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;customer_email&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Customer email&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;total&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Order amount&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;created_at&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Order creation date&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Your application already has an &lt;code&gt;App\Models\Order&lt;/code&gt; Eloquent model.&lt;/p&gt;

&lt;p&gt;A typical export begins with this command:&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 make:export OrdersExport &lt;span class="nt"&gt;--model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Order
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If Artisan reports that the command does not exist, install Laravel Excel first:&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 maatwebsite/excel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This installs the package version compatible with your project's Composer dependencies. Check which version was selected:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer show maatwebsite/excel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For an existing installation, you don't need to reinstall the package.&lt;/p&gt;

&lt;p&gt;The first implementation developers often write looks 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\Exports&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Models\Order&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;Maatwebsite\Excel\Concerns\FromCollection&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;OrdersExport&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;FromCollection&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;collection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the controller might return:&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;return&lt;/span&gt; &lt;span class="nc"&gt;Excel&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;download&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OrdersExport&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="s1"&gt;'orders.xlsx'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works for small datasets because the entire result fits comfortably in memory.&lt;/p&gt;

&lt;p&gt;The problem is here:&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;return&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Eloquent loads every matching record into a collection before Laravel Excel begins processing it.&lt;/p&gt;

&lt;p&gt;Every record becomes an Eloquent model containing attributes and additional object overhead. On top of that, PhpSpreadsheet needs resources to construct the workbook.&lt;/p&gt;

&lt;p&gt;For a sufficiently large dataset, PHP may fail with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Allowed memory size of 134217728 bytes exhausted
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact memory limit and error location depend on your PHP configuration and the amount of data.&lt;/p&gt;

&lt;p&gt;Another possible symptom is an HTTP timeout while the browser waits for the export.&lt;/p&gt;

&lt;p&gt;Increasing &lt;code&gt;memory_limit&lt;/code&gt; might temporarily hide the problem, but it doesn't remove the underlying inefficient data-loading approach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result at this stage:&lt;/strong&gt; You have identified whether your export retrieves the entire dataset before writing the spreadsheet.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Export large data with chunk in laravel-excel using FromQuery
&lt;/h2&gt;

&lt;p&gt;The recommended solution for database-backed exports is Laravel Excel's &lt;code&gt;FromQuery&lt;/code&gt; concern.&lt;/p&gt;

&lt;p&gt;Unlike &lt;code&gt;FromCollection&lt;/code&gt;, it accepts an unexecuted Eloquent query. Laravel Excel then retrieves the results in chunks rather than requiring you to load all matching records at once.&lt;/p&gt;

&lt;p&gt;Replace &lt;code&gt;app/Exports/OrdersExport.php&lt;/code&gt; with:&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\Exports&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Models\Order&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;Maatwebsite\Excel\Concerns\FromQuery&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;Maatwebsite\Excel\Concerns\WithHeadings&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;Maatwebsite\Excel\Concerns\WithMapping&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;OrdersExport&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt;
    &lt;span class="nc"&gt;FromQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;WithHeadings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;WithMapping&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;query&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Order&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;select&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
                &lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'order_number'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'customer_email'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'total'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'created_at'&lt;/span&gt;&lt;span class="p"&gt;,&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;orderBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;headings&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;'ID'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'Order Number'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'Customer Email'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'Total'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'Created At'&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="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$order&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="nv"&gt;$order&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;order_number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;customer_email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="o"&gt;?-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Y-m-d H:i:s'&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;The crucial detail is that &lt;code&gt;query()&lt;/code&gt; returns a builder.&lt;/p&gt;

&lt;p&gt;Don't do 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="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Order&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;get&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;And don't do 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="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both execute the database query and return the records immediately.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;FromQuery&lt;/code&gt;, Laravel Excel controls when and how the query runs.&lt;/p&gt;

&lt;p&gt;Notice three other decisions in the working example.&lt;/p&gt;

&lt;p&gt;First, &lt;code&gt;select()&lt;/code&gt; retrieves only the fields required by the spreadsheet. This avoids loading unnecessary model attributes.&lt;/p&gt;

&lt;p&gt;Second, &lt;code&gt;orderBy('id')&lt;/code&gt; provides a deterministic ordering for the export. This is useful when processing results across multiple queries, although concurrent database modifications can still affect exports.&lt;/p&gt;

&lt;p&gt;Third, &lt;code&gt;WithMapping&lt;/code&gt; explicitly controls the spreadsheet columns. You don't need to export every model property.&lt;/p&gt;

&lt;p&gt;According to the &lt;a href="https://docs.laravel-excel.com/3.1/exports/from-query.html" rel="noopener noreferrer"&gt;official Laravel Excel FromQuery documentation&lt;/a&gt;, chunking happens automatically when using this concern.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; The export now processes order records in database batches rather than loading the entire result into one collection.&lt;/p&gt;

&lt;p&gt;One distinction matters: database chunking reduces the memory required for retrieving records, but it doesn't guarantee constant total memory usage. Generating a large XLSX workbook can still consume substantial memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Control the export chunk size without manual loops
&lt;/h2&gt;

&lt;p&gt;Sometimes the default export chunk size isn't suitable for your workload.&lt;/p&gt;

&lt;p&gt;Laravel Excel provides the &lt;code&gt;WithCustomChunkSize&lt;/code&gt; concern for controlling how many query records are processed per chunk.&lt;/p&gt;

&lt;p&gt;Modify the export class declaration:&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;Maatwebsite\Excel\Concerns\WithCustomChunkSize&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;OrdersExport&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt;
    &lt;span class="nc"&gt;FromQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;WithHeadings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;WithMapping&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;WithCustomChunkSize&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Keep the query(), headings(), and map()&lt;/span&gt;
    &lt;span class="c1"&gt;// methods from the previous step.&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;chunkSize&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1000&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;Add the &lt;code&gt;use&lt;/code&gt; statement and &lt;code&gt;chunkSize()&lt;/code&gt; method to the existing export class; don't remove the implementations from Step 2.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;1000&lt;/code&gt; value is an example configuration, not a universally optimal setting.&lt;/p&gt;

&lt;p&gt;Smaller chunks reduce the number of database records handled simultaneously but may require more queries and queued jobs.&lt;/p&gt;

&lt;p&gt;Larger chunks reduce query overhead but can increase memory consumption during processing.&lt;/p&gt;

&lt;p&gt;Choose a value based on actual measurements, especially if individual rows contain large text fields or require additional database relationships.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why not call chunk() manually?
&lt;/h3&gt;

&lt;p&gt;You might find examples 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="nc"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&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;$orders&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Export each batch...&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 &lt;code&gt;chunk()&lt;/code&gt; method is useful when processing records yourself. However, manually calling it inside a normal Laravel Excel export doesn't automatically create one continuous spreadsheet.&lt;/p&gt;

&lt;p&gt;You would need to coordinate writing and appending the batches.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;FromQuery&lt;/code&gt;, Laravel Excel already manages the underlying query chunks.&lt;/p&gt;

&lt;p&gt;Also, don't confuse &lt;code&gt;WithCustomChunkSize&lt;/code&gt; with &lt;code&gt;WithChunkReading&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;WithChunkReading&lt;/code&gt; belongs to Laravel Excel's import workflow. It is commonly used when reading large Excel files into Laravel, not when exporting database records.&lt;/p&gt;

&lt;p&gt;See the &lt;a href="https://docs.laravel-excel.com/3.1/exports/concerns.html" rel="noopener noreferrer"&gt;Laravel Excel export concerns reference&lt;/a&gt; for the supported interfaces.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; Your export retrieves records in a controlled chunk size without custom database loops.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Queue the Laravel Excel export to prevent request timeouts
&lt;/h2&gt;

&lt;p&gt;Chunking solves one part of the problem: retrieving too much database data at once.&lt;/p&gt;

&lt;p&gt;However, an export may still take longer than the PHP request timeout or web server timeout.&lt;/p&gt;

&lt;p&gt;This is why a chunked export can work through Artisan but fail when triggered from the browser.&lt;/p&gt;

&lt;p&gt;For large reports, queueing is generally a better approach than forcing the user to wait for a synchronous download.&lt;/p&gt;

&lt;p&gt;Laravel Excel supports queued exports directly.&lt;/p&gt;

&lt;p&gt;First, configure a queue connection in &lt;code&gt;.env&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Make sure your application's queue tables exist. Newer Laravel application templates may already include their migrations.&lt;/p&gt;

&lt;p&gt;If your project doesn't have a jobs-table migration, generate one using the appropriate command for your Laravel version:&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 make:queue-table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Older Laravel installations may use:&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 queue:table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run migrations after creating any missing table:&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 migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then start a queue worker:&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 queue:work database &lt;span class="nt"&gt;--tries&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3 &lt;span class="nt"&gt;--timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;300
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The timeout shown is an example. Configure the queue connection's &lt;code&gt;retry_after&lt;/code&gt; value to exceed the worker timeout, and use worker settings appropriate for your workload.&lt;/p&gt;

&lt;p&gt;Now create a controller:&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 make:controller OrderExportController
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;app/Http/Controllers/OrderExportController.php&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Http\Controllers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Exports\OrdersExport&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Http\RedirectResponse&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;OrderExportController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Controller&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;export&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;RedirectResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OrdersExport&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;queue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'exports/orders.xlsx'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'local'&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;back&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;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'success'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'Your export has been queued.'&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;The &lt;code&gt;queue()&lt;/code&gt; method is available through Laravel Excel's &lt;code&gt;Exportable&lt;/code&gt; trait, so add it to the export class:&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;Maatwebsite\Excel\Concerns\Exportable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside the class:&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;Exportable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For clarity, the export class now implements &lt;code&gt;FromQuery&lt;/code&gt;, &lt;code&gt;WithHeadings&lt;/code&gt;, &lt;code&gt;WithMapping&lt;/code&gt;, and &lt;code&gt;WithCustomChunkSize&lt;/code&gt;, uses the &lt;code&gt;Exportable&lt;/code&gt; trait, and retains all four methods from the earlier steps.&lt;/p&gt;

&lt;p&gt;Register the route in &lt;code&gt;routes/web.php&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Http\Controllers\OrderExportController&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Route&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'auth'&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;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'/orders/export'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;OrderExportController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'export'&lt;/span&gt;&lt;span class="p"&gt;]&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;name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'orders.export'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The route is protected by Laravel's authentication middleware, although you should also add any application-specific export authorization.&lt;/p&gt;

&lt;p&gt;To trigger it from an authenticated Blade page:&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;form method="POST" action="{{ route('orders.export') }}"&amp;gt;
    @csrf

    &amp;lt;button type="submit"&amp;gt;
        Export Orders
    &amp;lt;/button&amp;gt;
&amp;lt;/form&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a user clicks the button, Laravel dispatches the export to the queue rather than waiting for the entire workbook to be generated.&lt;/p&gt;

&lt;p&gt;The background worker processes the export chunks and saves the resulting file to the configured disk.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Queuing returns immediately, but it does not immediately provide a completed downloadable file.&lt;/p&gt;

&lt;p&gt;Your application should show an export status and only offer a download after completion.&lt;/p&gt;

&lt;p&gt;This example uses a fixed filename for simplicity. In production, generate a unique filename per export request to prevent users from overwriting one another's reports. Downloads must also be authorized against the requesting user.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Fix Laravel Excel out-of-memory and failed queue jobs
&lt;/h2&gt;

&lt;p&gt;If the queued export still fails, don't immediately increase PHP memory and assume the problem is resolved.&lt;/p&gt;

&lt;p&gt;Check the failure category first.&lt;/p&gt;

&lt;h3&gt;
  
  
  The worker never processes the export
&lt;/h3&gt;

&lt;p&gt;If the controller reports success but no file appears, verify that the queue worker is running.&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 queue:work database &lt;span class="nt"&gt;--tries&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3 &lt;span class="nt"&gt;--timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;300
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inspect failed jobs:&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 queue:failed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To inspect the application log, check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;storage/logs/laravel.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you corrected the underlying error, retry an appropriate failed job using its recorded identifier:&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 queue:retry FAILED_JOB_ID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;FAILED_JOB_ID&lt;/code&gt; with an actual identifier reported by Artisan.&lt;/p&gt;

&lt;p&gt;Queued jobs don't complete merely because they were dispatched. A worker must actively consume them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Memory is still exhausted
&lt;/h3&gt;

&lt;p&gt;If &lt;code&gt;FromQuery&lt;/code&gt; is already implemented, check the size and complexity of each spreadsheet row.&lt;/p&gt;

&lt;p&gt;Avoid unnecessarily loading relationships or calculating expensive values inside &lt;code&gt;map()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example, this can introduce repeated database queries:&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;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$order&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="nv"&gt;$order&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="o"&gt;?-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&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;If the related &lt;code&gt;customer&lt;/code&gt; isn't loaded, accessing it may trigger additional queries.&lt;/p&gt;

&lt;p&gt;Consider an appropriately scoped eager load or a database join. Select the approach based on the actual relationships and the size of the export.&lt;/p&gt;

&lt;p&gt;If the spreadsheet contains extensive styling, formulas, images, or very wide rows, PhpSpreadsheet's workbook memory requirements may become the limiting factor even though database queries are chunked.&lt;/p&gt;

&lt;p&gt;For tabular reports that don't require XLSX features, CSV may be a better format.&lt;/p&gt;

&lt;h3&gt;
  
  
  Queue jobs run but the output is incomplete
&lt;/h3&gt;

&lt;p&gt;Queued exports rely on multiple jobs processing the same workbook.&lt;/p&gt;

&lt;p&gt;On a multi-server deployment, check whether workers have access to shared temporary files. Laravel Excel supports configuring a remote temporary-files disk for this situation.&lt;/p&gt;

&lt;p&gt;For complex queries containing &lt;code&gt;groupBy&lt;/code&gt;, the standard query count may not reflect the number of result rows. In that situation, Laravel Excel's &lt;code&gt;WithCustomQuerySize&lt;/code&gt; concern can supply the correct row count for queued job calculation.&lt;/p&gt;

&lt;p&gt;Also check for records being inserted, deleted, or modified during a long-running export. Ordinary chunked queries don't automatically provide a consistent database snapshot.&lt;/p&gt;

&lt;h3&gt;
  
  
  A MySQL data error appears during report preparation
&lt;/h3&gt;

&lt;p&gt;Exporting rows normally reads data rather than inserting it. But some systems first populate staging or reporting tables before generating spreadsheets.&lt;/p&gt;

&lt;p&gt;If that preparatory process produces a &lt;code&gt;Data truncated for column&lt;/code&gt; error, fix the database value or column definition separately. It isn't solved by changing the Excel chunk size.&lt;/p&gt;

&lt;p&gt;See &lt;a href="https://headsntail.com/blog/mysql-data-truncated-char1-column-fix" rel="noopener noreferrer"&gt;Data Truncated for Column at Row 1: Cause and Fix&lt;/a&gt; for that related database issue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; You can distinguish memory exhaustion, request timeouts, failed workers, missing temporary files, and source-data errors instead of treating them as the same problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Verify that the chunked export contains every order
&lt;/h2&gt;

&lt;p&gt;A successful queue response doesn't prove that the final spreadsheet is complete.&lt;/p&gt;

&lt;p&gt;Verification should include the stored file, the number of exported rows, and a check of sample records.&lt;/p&gt;

&lt;p&gt;For the controller example, wait until the queue worker finishes, then 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 tinker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside Tinker:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="nc"&gt;Storage&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;disk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'local'&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;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'exports/orders.xlsx'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output after a successful export:&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="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the file size:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Storage&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;disk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'local'&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;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'exports/orders.xlsx'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A positive size proves that a file exists, but not that every expected record was written.&lt;/p&gt;

&lt;p&gt;For a smaller verification dataset, open the spreadsheet and compare its exported data rows with the database query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;\App\Models\Order&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="nb"&gt;count&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since the example contains one heading row, the spreadsheet should have one more row than the number of exported orders, provided that each order maps to exactly one row.&lt;/p&gt;

&lt;p&gt;You can also test that the controller dispatches a queued export without generating a real spreadsheet. Laravel Excel provides a facade fake for this purpose.&lt;/p&gt;

&lt;p&gt;Example feature test:&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;Tests\Feature&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Models\User&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\Foundation\Testing\RefreshDatabase&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;Maatwebsite\Excel\Facades\Excel&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;Tests\TestCase&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;OrderExportTest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;TestCase&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;RefreshDatabase&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;test_orders_export_is_queued&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;Excel&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;fake&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;factory&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;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;actingAs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&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;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'orders.export'&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;assertRedirect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="nc"&gt;Excel&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;assertQueued&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'exports/orders.xlsx'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'local'&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;Run it using:&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 &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;--filter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;OrderExportTest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This verifies that the application queues the intended export. It does not prove that the actual workbook is complete or that the queue worker can process it.&lt;/p&gt;

&lt;p&gt;For that, perform an integration test with a real worker and compare the file contents against a controlled dataset.&lt;/p&gt;

&lt;h3&gt;
  
  
  Next steps
&lt;/h3&gt;

&lt;p&gt;Once the export works reliably, add unique filenames, export progress tracking, completion notifications, and secure download links. Measure query duration, peak memory, worker runtime, and final workbook size before tuning chunk settings. For particularly large reports, consider streaming or background-generated CSV files instead of creating a heavily formatted XLSX workbook.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Does Laravel Excel automatically export data in chunks?
&lt;/h3&gt;

&lt;p&gt;Yes, when you use the &lt;code&gt;FromQuery&lt;/code&gt; concern, Laravel Excel processes the returned database query in chunks. You don't need to manually call Eloquent's &lt;code&gt;chunk()&lt;/code&gt; method. This differs from exporting an already-loaded collection, which may consume significant memory before spreadsheet generation begins.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the best chunk size for Laravel Excel exports?
&lt;/h3&gt;

&lt;p&gt;There is no single best chunk size for every application. The right value depends on the size of each record, query complexity, available memory, and whether the export runs through a queue. Start with a reasonable value, such as the example's 1000 records, then measure performance and adjust.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why does Laravel Excel still run out of memory with FromQuery?
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;FromQuery&lt;/code&gt; reduces the amount of database data retrieved at once, but XLSX generation still requires memory for spreadsheet processing. Large cell contents, styling, formulas, relationships, or other workbook operations can increase memory usage. Try reducing chunk size and unnecessary processing; consider CSV for very large, mostly unformatted datasets.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I use WithChunkReading to export records?
&lt;/h3&gt;

&lt;p&gt;No. &lt;code&gt;WithChunkReading&lt;/code&gt; is intended for importing large spreadsheets into Laravel. For database exports, use &lt;code&gt;FromQuery&lt;/code&gt;; if you need to control the export chunk size, use &lt;code&gt;WithCustomChunkSize&lt;/code&gt;. Keeping import and export concerns separate prevents one of the most common implementation mistakes.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I export millions of records without a browser timeout?
&lt;/h3&gt;

&lt;p&gt;Use a queued &lt;code&gt;FromQuery&lt;/code&gt; export so that the HTTP request only starts the background work. Ensure that queue workers, temporary storage, and completion handling are configured correctly. For extremely large datasets, a CSV export or splitting the output into multiple files may be more practical than one XLSX workbook. If your goal is to &lt;strong&gt;export large data with chunk in laravel-excel&lt;/strong&gt;, start with &lt;code&gt;FromQuery&lt;/code&gt; and queueing, then choose the output format based on measured memory usage and actual reporting requirements.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://headsntail.com/blog/laravel-excel-large-data-chunk-export" rel="noopener noreferrer"&gt;headsntail.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Fix curl (35) ssl3_get_record:wrong version number on Nginx</title>
      <dc:creator>Faizan</dc:creator>
      <pubDate>Sat, 17 Oct 2026 11:09:38 +0000</pubDate>
      <link>https://dev.to/faizan050/fix-curl-35-ssl3getrecordwrong-version-number-on-nginx-3hpn</link>
      <guid>https://dev.to/faizan050/fix-curl-35-ssl3getrecordwrong-version-number-on-nginx-3hpn</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl: (35) error:1408F10B:SSL routines:ssl3_get_record:wrong version number
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You run &lt;code&gt;curl https://example.com&lt;/code&gt; against your Nginx server and get the error above instead of a page. If you searched for "nginx error https . curl: (35) error:1408f10b:ssl routines:ssl3_get_record:wrong version number", the cause is almost always one of these three:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Nginx listens on 443 without &lt;code&gt;ssl&lt;/code&gt;.&lt;/strong&gt; The port is open, but it serves plain HTTP.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You're calling &lt;code&gt;https://&lt;/code&gt; on a plain HTTP port.&lt;/strong&gt; Examples are &lt;code&gt;:80&lt;/code&gt;, &lt;code&gt;:8080&lt;/code&gt; or &lt;code&gt;php artisan serve&lt;/code&gt; on &lt;code&gt;:8000&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A proxy setting is wrong.&lt;/strong&gt; &lt;code&gt;https_proxy&lt;/code&gt; points at &lt;code&gt;https://...&lt;/code&gt; while the proxy itself only speaks plain HTTP.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Short answer:&lt;/strong&gt; curl sent a TLS handshake, and the server answered with plain HTTP. OpenSSL read the first bytes of that reply (&lt;code&gt;HTTP/1.1 ...&lt;/code&gt;) as a TLS record header, found a "version" that makes no sense, and stopped. To fix it, make the port speak TLS (&lt;code&gt;listen 443 ssl;&lt;/code&gt; with a certificate), or use &lt;code&gt;http://&lt;/code&gt; for that port.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick fix: add &lt;code&gt;ssl&lt;/code&gt; to the 443 listen directive
&lt;/h2&gt;

&lt;p&gt;In my experience this solves most cases. Someone writes &lt;code&gt;listen 443;&lt;/code&gt;, adds the certificate lines, and expects Nginx to switch on TLS by itself. It doesn't. The &lt;code&gt;ssl&lt;/code&gt; parameter on the &lt;code&gt;listen&lt;/code&gt; line is what enables TLS on that socket.&lt;/p&gt;

&lt;p&gt;Find your listen directives:&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="nb"&gt;sudo &lt;/span&gt;nginx &lt;span class="nt"&gt;-T&lt;/span&gt; 2&amp;gt;/dev/null | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"listen"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see &lt;code&gt;listen 443;&lt;/code&gt; or &lt;code&gt;listen [::]:443;&lt;/code&gt; without &lt;code&gt;ssl&lt;/code&gt;, fix the server block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="s"&gt;[::]:443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt; &lt;span class="s"&gt;www.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt;     &lt;span class="n"&gt;/etc/letsencrypt/live/example.com/fullchain.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/example.com/privkey.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="n"&gt;/var/www/example.com/public&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;index&lt;/span&gt; &lt;span class="s"&gt;index.php&lt;/span&gt; &lt;span class="s"&gt;index.html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="n"&gt;/index.php?&lt;/span&gt;&lt;span class="nv"&gt;$query_string&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;Test the config, then reload:&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="nb"&gt;sudo &lt;/span&gt;nginx &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl reload nginx
curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your config uses the old standalone &lt;code&gt;ssl on;&lt;/code&gt; directive, replace it with the &lt;code&gt;listen ... ssl&lt;/code&gt; form. That directive was deprecated a long time ago, and recent Nginx releases reject it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What causes the nginx error https . curl: (35) error:1408F10B:SSL routines:ssl3_get_record:wrong version number
&lt;/h2&gt;

&lt;p&gt;Go through each cause in turn. Each one has a quick check, so you aren't guessing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cause 1: Port 443 serves plain HTTP
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How to confirm:&lt;/strong&gt; request port 443 with plain HTTP.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-v&lt;/span&gt; http://example.com:443/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If this returns your normal page or a normal Nginx response, port 443 is not doing TLS. The access log also shows it clearly. Nginx logs the raw TLS handshake bytes as a broken request line:&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="nb"&gt;sudo tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 20 /var/log/nginx/access.log
&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;203.0.113.5 - - [...] "\x16\x03\x01\x02\x00\x01\x00\x01\xFC\x03\x03..." 400 157 "-" "-"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;\x16\x03\x01&lt;/code&gt; is the start of a TLS ClientHello. If you see it in the access log, your 443 listener is plain HTTP.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; add &lt;code&gt;ssl&lt;/code&gt; as shown in the quick fix. Check every server block that listens on 443, not just the one you edited, and pay special attention to any &lt;code&gt;default_server&lt;/code&gt; block. Also check that the site is actually enabled:&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="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; /etc/nginx/sites-enabled/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your HTTPS site exists in &lt;code&gt;sites-available&lt;/code&gt; but has no symlink in &lt;code&gt;sites-enabled&lt;/code&gt;, a different block is answering on 443. Create the link:&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="nb"&gt;sudo ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
&lt;span class="nb"&gt;sudo &lt;/span&gt;nginx &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl reload nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Cause 2: &lt;code&gt;https://&lt;/code&gt; used on an HTTP-only port
&lt;/h3&gt;

&lt;p&gt;This catches a lot of Laravel developers. &lt;code&gt;php artisan serve&lt;/code&gt; and most dev servers only speak plain HTTP, so &lt;code&gt;curl https://127.0.0.1:8000&lt;/code&gt; gives exactly this error. Use &lt;code&gt;http://127.0.0.1:8000&lt;/code&gt; instead. If the dev server won't start in the first place, see &lt;a href="https://headsntail.com/blog/php-artisan-serve-failed-to-listen-127-0-0-1-8000" rel="noopener noreferrer"&gt;php artisan serve: Failed to Listen on 127.0.0.1:8000&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The same applies to &lt;code&gt;https://example.com:80&lt;/code&gt; or to any app port behind Nginx, such as Node or Gunicorn on &lt;code&gt;:3000&lt;/code&gt; or &lt;code&gt;:8080&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to confirm:&lt;/strong&gt; remove the &lt;code&gt;s&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-I&lt;/span&gt; http://example.com:8080/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If that works, the port is plain HTTP.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; use the correct scheme for that port. To expose the app over HTTPS, let Nginx handle TLS on 443 and forward to the app over plain HTTP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:8080&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-Proto&lt;/span&gt; &lt;span class="nv"&gt;$scheme&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;The &lt;code&gt;proxy_pass&lt;/code&gt; target must be &lt;code&gt;http://&lt;/code&gt; unless the backend really serves TLS. Pointing &lt;code&gt;proxy_pass https://...&lt;/code&gt; at a plain backend produces the same "wrong version number" error, and it shows up in Nginx's error log.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cause 3: Docker or another service owns port 443
&lt;/h3&gt;

&lt;p&gt;A Docker mapping like &lt;code&gt;-p 443:80&lt;/code&gt; forwards host port 443 to the container's plain HTTP port. In that case no TLS ever happens, even though the port number looks right.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to confirm:&lt;/strong&gt;&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="nb"&gt;sudo &lt;/span&gt;ss &lt;span class="nt"&gt;-tlnp&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;':443'&lt;/span&gt;
docker ps &lt;span class="nt"&gt;--format&lt;/span&gt; &lt;span class="s1"&gt;'{{.Names}}\t{{.Ports}}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; map 443 to a container port that actually terminates TLS. Alternatively, keep the container on an internal HTTP port and let host Nginx handle 443 with &lt;code&gt;ssl&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cause 4: Wrong &lt;code&gt;https_proxy&lt;/code&gt; value
&lt;/h3&gt;

&lt;p&gt;Modern curl can talk TLS to the proxy itself. If your environment has &lt;code&gt;https_proxy=https://proxy.local:3128&lt;/code&gt; and the proxy only speaks HTTP, the handshake fails before your server is even contacted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to confirm:&lt;/strong&gt;&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="nb"&gt;env&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; proxy
curl &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nt"&gt;--noproxy&lt;/span&gt; &lt;span class="s1"&gt;'*'&lt;/span&gt; https://example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the request works with &lt;code&gt;--noproxy&lt;/code&gt;, the proxy setting is the problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; point the variable at the proxy using &lt;code&gt;http://&lt;/code&gt;. It still tunnels HTTPS traffic with CONNECT:&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="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;https_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://proxy.local:3128
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Variations of the "wrong version number" error
&lt;/h2&gt;

&lt;p&gt;The wording depends on your OpenSSL version. On OpenSSL 3 you will usually see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl: (35) OpenSSL/3.0.13: error:0A00010B:SSL routines::wrong version number
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It has the same meaning and the same fixes. PHP's &lt;code&gt;curl_exec()&lt;/code&gt;, Guzzle and Laravel's &lt;code&gt;Http::&lt;/code&gt; client report the same underlying error, often as &lt;code&gt;cURL error 35&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  If nothing worked: gather the evidence
&lt;/h2&gt;

&lt;p&gt;Collect these before you change anything else:&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;# Full handshake view from the client side&lt;/span&gt;
curl &lt;span class="nt"&gt;-v&lt;/span&gt; https://example.com 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 30

&lt;span class="c"&gt;# What the server actually answers on 443&lt;/span&gt;
openssl s_client &lt;span class="nt"&gt;-connect&lt;/span&gt; example.com:443 &lt;span class="nt"&gt;-servername&lt;/span&gt; example.com &amp;lt;/dev/null

&lt;span class="c"&gt;# Effective config, exactly as Nginx loaded it&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;nginx &lt;span class="nt"&gt;-T&lt;/span&gt; 2&amp;gt;/dev/null | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-nE&lt;/span&gt; &lt;span class="s2"&gt;"server_name|listen|ssl_certificate"&lt;/span&gt;

&lt;span class="c"&gt;# Recent errors&lt;/span&gt;
&lt;span class="nb"&gt;sudo tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 50 /var/log/nginx/error.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;openssl s_client&lt;/code&gt; prints &lt;code&gt;wrong version number&lt;/code&gt; and no certificate, the listener isn't doing TLS at all. Go back to Cause 1 or Cause 3. If it shows a certificate chain, the server side is fine, and the problem is on the client side: a proxy, a wrong port in the URL, or a stale DNS record pointing to a different machine. Running &lt;code&gt;dig +short example.com&lt;/code&gt; quickly rules out that last one.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What does "wrong version number" mean in curl?
&lt;/h3&gt;

&lt;p&gt;curl expected a TLS record but got something else, usually a plain HTTP response. OpenSSL reads those bytes as a protocol version and rejects them. Despite the name, it is almost never a real TLS version mismatch.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does &lt;code&gt;curl -k&lt;/code&gt; fix this error?
&lt;/h3&gt;

&lt;p&gt;No. &lt;code&gt;-k&lt;/code&gt; only skips certificate verification, and this error happens before any certificate is exchanged. The handshake itself fails, so you have to fix the port or scheme.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why does the site open in my browser but fail with curl?
&lt;/h3&gt;

&lt;p&gt;The browser and curl are probably not hitting the same thing. The browser may follow a redirect from port 80, use different proxy settings, or show a cached page. Run &lt;code&gt;curl -v&lt;/code&gt; with the exact URL from the address bar to compare.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is error 0A00010B the same as 1408F10B?
&lt;/h3&gt;

&lt;p&gt;Yes. &lt;code&gt;0A00010B&lt;/code&gt; is the OpenSSL 3 code for the same "wrong version number" condition that OpenSSL 1.1 reports as &lt;code&gt;1408F10B&lt;/code&gt;. The causes and fixes are identical.&lt;/p&gt;

&lt;p&gt;To sum up: the nginx error https . curl: (35) error:1408F10B:SSL routines:ssl3_get_record:wrong version number means TLS went in and plain HTTP came back. Find which listener is answering on that port, give it &lt;code&gt;listen 443 ssl&lt;/code&gt; with a certificate, or use &lt;code&gt;http://&lt;/code&gt;, and the error goes away.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://headsntail.com/blog/nginx-curl-35-ssl3-get-record-wrong-version-number-fix" rel="noopener noreferrer"&gt;headsntail.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>linux</category>
      <category>nginx</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>php artisan serve: Failed to Listen on 127.0.0.1:8000 (reason: ?)</title>
      <dc:creator>Faizan</dc:creator>
      <pubDate>Sat, 17 Oct 2026 09:04:28 +0000</pubDate>
      <link>https://dev.to/faizan050/php-artisan-serve-failed-to-listen-on-1270018000-reason--1ghm</link>
      <guid>https://dev.to/faizan050/php-artisan-serve-failed-to-listen-on-1270018000-reason--1ghm</guid>
      <description>&lt;p&gt;The most common mistake with this error is assuming port 8000 is busy and trying &lt;code&gt;--port=8001&lt;/code&gt;, then &lt;code&gt;8002&lt;/code&gt;, then &lt;code&gt;8080&lt;/code&gt;, and getting the same error every time. When &lt;code&gt;php artisan serve (failed to listen on 127.0.0.1:8000 (reason: ?))&lt;/code&gt; shows up, the question mark means PHP didn't report a reason, and that missing reason is a clue in itself.&lt;/p&gt;

&lt;p&gt;Here's what you'll see in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Failed to listen on 127.0.0.1:8000 (reason: ?)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It usually comes from one of three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;variables_order&lt;/code&gt; in php.ini is missing the &lt;code&gt;E&lt;/code&gt;&lt;/strong&gt;, which breaks how &lt;code&gt;artisan serve&lt;/code&gt; starts PHP's built-in server. This is the most common cause on Windows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Another process is already using the port.&lt;/strong&gt; Often it's an old &lt;code&gt;artisan serve&lt;/code&gt; running in a terminal you forgot about.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Windows has reserved the port.&lt;/strong&gt; Hyper-V, WSL or Docker can block whole port ranges, and the port looks free when you check it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Short answer:&lt;/strong&gt; Open the php.ini used by your command line, find &lt;code&gt;variables_order = "GPCS"&lt;/code&gt;, and change it to &lt;code&gt;"EGPCS"&lt;/code&gt;. Then run &lt;code&gt;php artisan serve&lt;/code&gt; again. If it still fails, check what's using port 8000 with &lt;code&gt;netstat&lt;/code&gt;, and on Windows check the reserved port ranges with &lt;code&gt;netsh&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I'll use one setup throughout this article: a Laravel project at &lt;code&gt;C:\xampp\htdocs\shop&lt;/code&gt; on Windows with XAMPP. I've added the macOS and Linux commands where they're different.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Fix: Change variables_order in php.ini
&lt;/h2&gt;

&lt;p&gt;First, find out which php.ini your terminal actually uses. This isn't always the one you'd expect, especially if you have more than one PHP installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php &lt;span class="nt"&gt;--ini&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the line &lt;code&gt;Loaded Configuration File&lt;/code&gt;. On a default XAMPP install it's &lt;code&gt;C:\xampp\php\php.ini&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now check the current value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s2"&gt;"echo ini_get('variables_order');"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it prints &lt;code&gt;GPCS&lt;/code&gt;, that's your problem. Open that php.ini, search for &lt;code&gt;variables_order&lt;/code&gt;, and change it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;; before
&lt;/span&gt;&lt;span class="py"&gt;variables_order&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"GPCS"&lt;/span&gt;

&lt;span class="c"&gt;; after
&lt;/span&gt;&lt;span class="py"&gt;variables_order&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"EGPCS"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save the file, &lt;strong&gt;open a new terminal&lt;/strong&gt; so nothing from the old session is reused, and try again:&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="nb"&gt;cd &lt;/span&gt;C:&lt;span class="se"&gt;\x&lt;/span&gt;ampp&lt;span class="se"&gt;\h&lt;/span&gt;tdocs&lt;span class="se"&gt;\s&lt;/span&gt;hop
php artisan serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should now see &lt;code&gt;Server running on [http://127.0.0.1:8000]&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why this one setting matters
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;artisan serve&lt;/code&gt; doesn't serve your app directly. It starts a separate &lt;code&gt;php -S&lt;/code&gt; process and passes environment variables to it. The &lt;code&gt;E&lt;/code&gt; in &lt;code&gt;variables_order&lt;/code&gt; tells PHP to fill &lt;code&gt;$_ENV&lt;/code&gt;. Without it, Laravel can't pass those variables to the new process properly, the child process fails to start, and PHP has no specific reason to report. So you get the question mark.&lt;/p&gt;

&lt;p&gt;To be clear about what's tested and what isn't: changing &lt;code&gt;GPCS&lt;/code&gt; to &lt;code&gt;EGPCS&lt;/code&gt; is a widely reported fix for this exact error, and it's the first thing I check. I'm not sure every Laravel and PHP version behaves the same way, so if the value already says &lt;code&gt;EGPCS&lt;/code&gt;, move on to the next causes.&lt;/p&gt;

&lt;p&gt;While you're editing php.ini, keep it open. Upload limits and POST size live in the same file, and &lt;a href="https://headsntail.com/blog/fix-php-post-request-capacity-limit" rel="noopener noreferrer"&gt;the PHP POST capacity limit guide&lt;/a&gt; covers those settings if you need them later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Diagnosing "Failed to Listen on 127.0.0.1:8000" Cause by Cause
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Cause 1: Something is already using port 8000
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How to confirm it on Windows:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;netstat &lt;span class="nt"&gt;-ano&lt;/span&gt; | findstr :8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see a &lt;code&gt;LISTENING&lt;/code&gt; line, the last column is the process ID. Look it up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tasklist /FI &lt;span class="s2"&gt;"PID eq 12345"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;On macOS or Linux:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lsof &lt;span class="nt"&gt;-i&lt;/span&gt; :8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; If it's an old &lt;code&gt;php.exe&lt;/code&gt; from an earlier &lt;code&gt;artisan serve&lt;/code&gt;, stop it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;taskkill /PID 12345 /F
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On macOS or Linux, use &lt;code&gt;kill 12345&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If it's something you want to keep running (another dev server, a Docker container), just pick a different port:&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 serve &lt;span class="nt"&gt;--port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One detail worth knowing: when you don't pass &lt;code&gt;--port&lt;/code&gt;, newer versions of Laravel try the next few ports automatically if 8000 is taken. So if you see the error even though Laravel moved through several ports, the port itself probably isn't the issue. Go back to the quick fix or check Cause 2.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cause 2: Windows has reserved the port
&lt;/h3&gt;

&lt;p&gt;This one is frustrating. &lt;code&gt;netstat&lt;/code&gt; shows nothing on port 8000, but Windows still won't let PHP bind to it. Hyper-V, WSL 2 and Docker Desktop can reserve blocks of ports, and those ports are off-limits even though nothing is using them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to confirm:&lt;/strong&gt; Open Command Prompt &lt;strong&gt;as Administrator&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;netsh interface ipv4 show excludedportrange &lt;span class="nv"&gt;protocol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If 8000 falls inside one of the ranges listed, that's your cause.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; The simplest option is to choose a port outside every listed range:&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 serve &lt;span class="nt"&gt;--port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8888
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you really need 8000, restarting the Windows NAT service often frees the reservations. In an Administrator prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;net stop winnat
net start winnat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Stopping &lt;code&gt;winnat&lt;/code&gt; briefly interrupts networking for WSL and Docker, so close those first. The reserved ranges can come back after a reboot. Personally, I just keep my Laravel projects on a port I know is outside the ranges and don't worry about it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cause 3: Laravel is using a different PHP than you think
&lt;/h3&gt;

&lt;p&gt;XAMPP, Laragon, Herd, Chocolatey and manual installs can all add their own &lt;code&gt;php.exe&lt;/code&gt; to your PATH. You might fix the right php.ini for the wrong PHP.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to confirm:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;where php
php &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On macOS or Linux, use &lt;code&gt;which php&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;where php&lt;/code&gt; lists more than one path, the first one is what runs. Check that &lt;code&gt;php --ini&lt;/code&gt; points to the file you edited.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Edit the php.ini that belongs to the first PHP in the list, or reorder your PATH in Windows environment variables so the PHP you want comes first. Open a new terminal afterwards. Terminals that are already open keep the old PATH.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cause 4: Firewall, antivirus or host binding
&lt;/h3&gt;

&lt;p&gt;A security tool that blocks &lt;code&gt;php.exe&lt;/code&gt; from opening a port can produce the same vague error. And if &lt;code&gt;localhost&lt;/code&gt; resolves to IPv6 on your machine, binding to it can behave differently from &lt;code&gt;127.0.0.1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to confirm:&lt;/strong&gt; Try binding explicitly to a different address:&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 serve &lt;span class="nt"&gt;--host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;127.0.0.1 &lt;span class="nt"&gt;--port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8080
php artisan serve &lt;span class="nt"&gt;--host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.0.0.0 &lt;span class="nt"&gt;--port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;0.0.0.0&lt;/code&gt; works and &lt;code&gt;127.0.0.1&lt;/code&gt; doesn't, something on your machine is blocking the loopback address. If neither works and the earlier causes check out, temporarily allow &lt;code&gt;php.exe&lt;/code&gt; in your firewall or antivirus and test again. Turn the protection back on afterwards and add a proper exception instead of leaving it off.&lt;/p&gt;

&lt;h2&gt;
  
  
  If Nothing Worked: Find Out Whether It's Laravel or PHP
&lt;/h2&gt;

&lt;p&gt;This is the most useful test of the lot. It skips Laravel entirely and starts PHP's built-in server directly:&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="nb"&gt;cd &lt;/span&gt;C:&lt;span class="se"&gt;\x&lt;/span&gt;ampp&lt;span class="se"&gt;\h&lt;/span&gt;tdocs&lt;span class="se"&gt;\s&lt;/span&gt;hop
php &lt;span class="nt"&gt;-S&lt;/span&gt; 127.0.0.1:8000 &lt;span class="nt"&gt;-t&lt;/span&gt; public
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;If this works&lt;/strong&gt;, PHP can listen on the port, and the problem is in how &lt;code&gt;artisan serve&lt;/code&gt; starts the server. That almost always points back to &lt;code&gt;variables_order&lt;/code&gt; or to the PHP version mismatch in Cause 3.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If this also fails&lt;/strong&gt;, PHP prints a real reason this time (something like "Address already in use" or an access-permissions message). That points to Cause 1, 2 or 4.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For more detail from Laravel itself, run the command in verbose mode:&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 serve &lt;span class="nt"&gt;-vvv&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if you're asking someone for help on Stack Overflow or in a team chat, include the output of these commands. They answer most of the follow-up questions straight away:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php &lt;span class="nt"&gt;-v&lt;/span&gt;
php &lt;span class="nt"&gt;--ini&lt;/span&gt;
php &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s2"&gt;"echo ini_get('variables_order');"&lt;/span&gt;
where php
netstat &lt;span class="nt"&gt;-ano&lt;/span&gt; | findstr :8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the server is running, your next local issue is usually the database. The &lt;a href="https://headsntail.com/blog/laravel-migrate-fresh-seed-table-not-seeding-mysql" rel="noopener noreferrer"&gt;migrate:fresh --seed troubleshooting guide&lt;/a&gt; picks up from there.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What does "reason: ?" mean in php artisan serve?
&lt;/h3&gt;

&lt;p&gt;It means PHP failed to start the server but didn't give a specific reason. With a busy port you'd normally see "Address already in use". The question mark usually means the problem happened while starting the server process, which is why the &lt;code&gt;variables_order&lt;/code&gt; setting is the first thing to check.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I change the default port for php artisan serve?
&lt;/h3&gt;

&lt;p&gt;Yes. Pass &lt;code&gt;--port=8080&lt;/code&gt; on the command line. You can also set &lt;code&gt;SERVER_PORT=8080&lt;/code&gt; in your &lt;code&gt;.env&lt;/code&gt; file, and newer Laravel versions use it as the default. If you're not sure your version supports that, the &lt;code&gt;--port&lt;/code&gt; flag always works.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is it safe to set variables_order to "EGPCS"?
&lt;/h3&gt;

&lt;p&gt;For local development, yes, and it's PHP's own built-in default. The production php.ini template leaves out &lt;code&gt;E&lt;/code&gt; to save a bit of memory, but on your local machine that doesn't make a noticeable difference. Don't change it on a production server without checking with whoever manages that server.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why does php artisan serve (failed to listen on 127.0.0.1:8000 (reason: ?)) only happen on Windows?
&lt;/h3&gt;

&lt;p&gt;It can happen anywhere, but Windows causes two of the three common triggers. XAMPP and other Windows PHP bundles often ship a php.ini with &lt;code&gt;variables_order = "GPCS"&lt;/code&gt;, and Windows reserves port ranges for Hyper-V and WSL. On macOS and Linux, the cause is almost always a process already using the port, which &lt;code&gt;lsof -i :8000&lt;/code&gt; finds quickly.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://headsntail.com/blog/php-artisan-serve-failed-to-listen-127-0-0-1-8000" rel="noopener noreferrer"&gt;headsntail.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
