<?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>Forem: PHPControls</title>
    <description>The latest articles on Forem by PHPControls (@phpcontrols).</description>
    <link>https://forem.com/phpcontrols</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2160088%2F3a5ae848-1135-457d-a645-322c10843e5c.png</url>
      <title>Forem: PHPControls</title>
      <link>https://forem.com/phpcontrols</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/phpcontrols"/>
    <language>en</language>
    <item>
      <title>Understanding Asymmetric Property Visibility in PHP 8.4</title>
      <dc:creator>PHPControls</dc:creator>
      <pubDate>Tue, 25 Mar 2025 15:24:00 +0000</pubDate>
      <link>https://forem.com/phpcontrols/understanding-asymmetric-property-visibility-in-php-84-4ch6</link>
      <guid>https://forem.com/phpcontrols/understanding-asymmetric-property-visibility-in-php-84-4ch6</guid>
      <description>&lt;p&gt;PHP 8.4, released in November 2024, introduces &lt;strong&gt;&lt;a href="https://www.php.net/manual/en/language.oop5.visibility.php" rel="noopener noreferrer"&gt;Asymmetric Property Visibility&lt;/a&gt;&lt;/strong&gt;, which allows separate visibility levels for reading and writing class properties, enhancing access control while preserving encapsulation.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Asymmetric Property Visibility?
&lt;/h3&gt;

&lt;p&gt;In &lt;strong&gt;PHP 8.4&lt;/strong&gt;, you can now &lt;strong&gt;define different visibility levels for reading and writing a property&lt;/strong&gt; within a class.&lt;/p&gt;

&lt;p&gt;Previously, PHP allowed properties to be &lt;code&gt;public&lt;/code&gt;, &lt;code&gt;protected&lt;/code&gt;, or &lt;code&gt;private&lt;/code&gt;, but &lt;strong&gt;both reading and writing had the same visibility level&lt;/strong&gt;. With &lt;strong&gt;Asymmetric Property Visibility&lt;/strong&gt;, you can set &lt;strong&gt;separate visibility for getting and setting a property&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  A Basic Example
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;set&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;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;)&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="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Allowed: private setter is used inside the class&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;changeName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$newName&lt;/span&gt;&lt;span class="p"&gt;)&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="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$newName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Allowed: inside class&lt;/span&gt;
    &lt;span class="p"&gt;}&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Alice"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$user&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="c1"&gt;// ✅ Allowed: public getter&lt;/span&gt;
&lt;span class="nv"&gt;$user&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="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Bob"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ❌ Error: Cannot modify, setter is private&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Key Takeaways
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;get&lt;/code&gt; visibility is &lt;strong&gt;public&lt;/strong&gt;, allowing &lt;strong&gt;read access&lt;/strong&gt; from anywhere.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;set&lt;/code&gt; visibility is &lt;strong&gt;private&lt;/strong&gt;, so &lt;strong&gt;only class methods&lt;/strong&gt; can modify the property.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Example 2: Preventing Direct Modification of Sensitive Properties
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BankAccount&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$balance&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;set&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;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$initialBalance&lt;/span&gt;&lt;span class="p"&gt;)&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="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$initialBalance&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;deposit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$amount&lt;/span&gt;&lt;span class="p"&gt;)&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="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nv"&gt;$amount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ✅ Allowed: inside class&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;withdraw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$amount&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="nv"&gt;$amount&lt;/span&gt; &lt;span class="o"&gt;&amp;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="n"&gt;balance&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;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Insufficient funds"&lt;/span&gt;&lt;span class="p"&gt;);&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="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="nv"&gt;$amount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ✅ Allowed: inside class&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$account&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BankAccount&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;echo&lt;/span&gt; &lt;span class="nv"&gt;$account&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ✅ Allowed: public getter&lt;/span&gt;
&lt;span class="nv"&gt;$account&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ❌ Error: Cannot modify, setter is private&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Key Takeaways
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;  Prevents &lt;strong&gt;unauthorized modifications&lt;/strong&gt; to &lt;code&gt;$balance&lt;/code&gt; while allowing &lt;strong&gt;controlled updates&lt;/strong&gt; through class methods.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Improves security&lt;/strong&gt; by ensuring logic (e.g., preventing overdrafts) is &lt;strong&gt;always enforced&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Caveats &amp;amp; Considerations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  This feature &lt;strong&gt;only applies to&lt;/strong&gt; &lt;a href="https://phpgrid.com/blog/typed-properties-in-php-7-4/" rel="noopener noreferrer"&gt;&lt;strong&gt;typed properties&lt;/strong&gt;&lt;/a&gt; (&lt;code&gt;int&lt;/code&gt;, &lt;code&gt;string&lt;/code&gt;, &lt;code&gt;array&lt;/code&gt;, etc.). Typed properties are supported since &lt;a href="https://www.php.net/ChangeLog-7.php" rel="noopener noreferrer"&gt;PHP 7.4&lt;/a&gt;. &lt;/li&gt;
&lt;li&gt;  You &lt;strong&gt;must&lt;/strong&gt; specify a visibility level for &lt;strong&gt;both&lt;/strong&gt; &lt;code&gt;get&lt;/code&gt; and &lt;code&gt;set&lt;/code&gt; (e.g., &lt;code&gt;{ public get; private set; }&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  Asymmetric visibility &lt;strong&gt;cannot&lt;/strong&gt; be applied to untyped properties.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How Was Asymmetric Property Visibility Achieved Before PHP 8.4?
&lt;/h3&gt;

&lt;p&gt;Before &lt;strong&gt;Asymmetric Property Visibility&lt;/strong&gt;, PHP only allowed &lt;strong&gt;single visibility&lt;/strong&gt; for properties (&lt;code&gt;public&lt;/code&gt;, &lt;code&gt;protected&lt;/code&gt;, or &lt;code&gt;private&lt;/code&gt;). This meant that &lt;strong&gt;if a property was readable, it was also writable&lt;/strong&gt; unless additional methods were used to restrict modifications.&lt;/p&gt;

&lt;p&gt;To achieve similar behavior, developers had to use &lt;strong&gt;getter and setter methods&lt;/strong&gt; manually using Getter &amp;amp; Setter Methods (Manual Encapsulation)&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$name&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;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;)&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="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Public getter method&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;getName&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&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="c1"&gt;// Private setter method (prevents external modification)&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$name&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;changeName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$newName&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$newName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Allowed inside class&lt;/span&gt;
    &lt;span class="p"&gt;}&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Alice"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getName&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// ✅ Allowed: public getter\&lt;/span&gt;
&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Bob"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ❌ Error: Cannot access private method\&lt;/span&gt;
&lt;span class="nv"&gt;$user&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="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Bob"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ❌ Error: Cannot access private property&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Problems with the Traditional Approach
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;More Boilerplate Code&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;  Requires &lt;strong&gt;explicit getter and setter methods&lt;/strong&gt; for each property.&lt;/li&gt;
&lt;li&gt;  Increases &lt;strong&gt;code duplication&lt;/strong&gt; when dealing with many properties.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Less Readable &amp;amp; Natural Code&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Instead of &lt;code&gt;$user-&amp;gt;name&lt;/code&gt;, you need to call &lt;code&gt;$user-&amp;gt;getName()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Assigning a value (&lt;code&gt;$user-&amp;gt;name = "Bob";&lt;/code&gt;) is replaced by a method (&lt;code&gt;$user-&amp;gt;changeName("Bob");&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why Asymmetric Property Visibility Matters
&lt;/h3&gt;

&lt;p&gt;Asymmetric Property Visibility in PHP 8.4 enhances encapsulation by allowing developers to set different visibility levels for reading and writing a property. This means a property can be &lt;strong&gt;publicly readable but privately writable&lt;/strong&gt;, preventing unintended modifications while still making data accessible. &lt;/p&gt;

&lt;p&gt;Previously, achieving this required workarounds like getter and setter methods, but now it can be done more cleanly and intuitively. This feature improves code maintainability, security, and clarity, making it easier to enforce strict control over property access without extra boilerplate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;Before PHP 8.4, &lt;strong&gt;getter and setter methods were the only way&lt;/strong&gt; to enforce asymmetric visibility. While effective, it resulted in &lt;strong&gt;verbose&lt;/strong&gt; and &lt;strong&gt;less readable&lt;/strong&gt; code. With &lt;strong&gt;Asymmetric Property Visibility&lt;/strong&gt;, PHP now provides &lt;strong&gt;native support&lt;/strong&gt; for defining different access levels for reading and writing properties, making &lt;strong&gt;property management much cleaner and more intuitive&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  About the Author
&lt;/h2&gt;

&lt;p&gt;The author is a full-stack web developer who created SQL-based data analytics and BI reports tool - Querro at (&lt;a href="https://querro.io" rel="noopener noreferrer"&gt;querro.io&lt;/a&gt;).&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Debugging PHP with VSCode and XDebug: A Step-by-Step Guide</title>
      <dc:creator>PHPControls</dc:creator>
      <pubDate>Sun, 09 Mar 2025 20:10:41 +0000</pubDate>
      <link>https://forem.com/phpcontrols/debugging-php-with-vscode-and-xdebug-a-step-by-step-guide-4296</link>
      <guid>https://forem.com/phpcontrols/debugging-php-with-vscode-and-xdebug-a-step-by-step-guide-4296</guid>
      <description>&lt;p&gt;Debugging is an essential part of PHP development, and using Visual Studio Code with XDebug can greatly enhance your workflow. This guide will walk you through setting up XDebug, enabling breakpoints, stepping through code, using stack traces, and troubleshooting common issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Installing XDebug
&lt;/h2&gt;

&lt;p&gt;Before you can debug PHP with VSCode, you need to ensure that XDebug is installed on your system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check if XDebug is Installed
&lt;/h3&gt;

&lt;p&gt;From a &lt;a href="https://www.php.net/manual/en/function.phpinfo.php" rel="noopener noreferrer"&gt;phpinfo&lt;/a&gt; page, and check wether XDebug section and it is enabled.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwxcop6czc0i4kdqh333r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwxcop6czc0i4kdqh333r.png" alt="XDebug in phpinfo" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Install XDebug If It's Not Yet Installed
&lt;/h3&gt;

&lt;p&gt;If XDebug is missing, you can install it using pecl:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pecl install xdebug
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installation, add this line to your &lt;code&gt;php.ini&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Remember to restart your web server or PHP service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl restart apache2  # For Apache
sudo systemctl restart php-fpm  # For PHP-FPM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need to configure XDebug to connect to VSCode&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Configuring XDebug for VSCode
&lt;/h2&gt;

&lt;p&gt;Edit your &lt;code&gt;php.ini&lt;/code&gt; file and add the following configuration:&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;[xdebug]&lt;/span&gt;
&lt;span class="py"&gt;xdebug.mode&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;debug&lt;/span&gt;
&lt;span class="py"&gt;xdebug.start_with_request&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;yes&lt;/span&gt;
&lt;span class="py"&gt;xdebug.client_host&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;127.0.0.1&lt;/span&gt;
&lt;span class="py"&gt;xdebug.client_port&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;9003&lt;/span&gt;
&lt;span class="py"&gt;xdebug.log&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var/log/xdebug.log&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ensure your PHP service is restarted for any changes made in php.ini to take effect.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Setting Up VSCode for XDebug
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Install the PHP Debug Extension
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Open VSCode.&lt;/li&gt;
&lt;li&gt;  Go to Extensions (&lt;code&gt;Ctrl+Shift+X&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  Search for &lt;a href="https://marketplace.visualstudio.com/items?itemName=xdebug.php-debug" rel="noopener noreferrer"&gt;PHP Debug by Felix Becker&lt;/a&gt; and install it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9qevyy3obzr1at0efx9w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9qevyy3obzr1at0efx9w.png" alt="PHP Debug Extension for VSCode" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Configure VSCode Debugger
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Open your project in VSCode.&lt;/li&gt;
&lt;li&gt;  Go to the Run and Debug panel (&lt;code&gt;Ctrl+Shift+D&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  Click on create a launch.json file. It should create default configuration as the following with port 9003. It is absolutely critical to have the same port as what is in xdebug.client_port in php.ini in previous step.
&lt;/li&gt;
&lt;/ul&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="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"configurations"&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="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;"Listen for XDebug"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"php"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"launch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9003&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;"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;"Launch currently open script"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"php"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"launch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"program"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${file}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"cwd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${fileDirname}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9003&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="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Start the Debugger
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Click the green Start Debugging button or press &lt;code&gt;F5&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Ensure XDebug is running and listening on port 9003. It actually can be any port number as 9003 is default.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The debugger bar should now appear right below tabs in VSCode.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmbk6y9sohzm69voffgiv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmbk6y9sohzm69voffgiv.png" alt="VSCode Debugger Bar" width="800" height="142"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Debugging Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Setting Breakpoints
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Open any PHP file.&lt;/li&gt;
&lt;li&gt;  Click in the left margin next to a line number or press &lt;code&gt;F9&lt;/code&gt; to set a breakpoint.&lt;/li&gt;
&lt;li&gt;  Run the debugger (&lt;code&gt;F5&lt;/code&gt;) and execute the PHP script in your browser.&lt;/li&gt;
&lt;li&gt;  The script execution will pause at the breakpoint.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Stepping Through Code
&lt;/h3&gt;

&lt;p&gt;While debugging, you can control execution using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Step Over (&lt;code&gt;F10&lt;/code&gt;) -- Move to the next line of code.&lt;/li&gt;
&lt;li&gt;  Step Into (&lt;code&gt;F11&lt;/code&gt;) -- Enter into function calls.&lt;/li&gt;
&lt;li&gt;  Step Out (&lt;code&gt;Shift+F11&lt;/code&gt;) -- Exit the current function.&lt;/li&gt;
&lt;li&gt;  Continue (&lt;code&gt;F5&lt;/code&gt;) -- Resume execution until the next breakpoint.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Learn to Use Stack Trace
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  The Call Stack panel in VSCode shows the sequence of function calls leading up to the breakpoint.&lt;/li&gt;
&lt;li&gt;  Helps trace errors in deeply nested functions.&lt;/li&gt;
&lt;li&gt;  Click on any function in the stack to inspect its execution.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9zcdixfub70u8i1inmm1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9zcdixfub70u8i1inmm1.png" alt="PHP XDebug breakpoint" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Troubleshooting Common Issues
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Issue 1: Debugger Not Stopping at Breakpoints
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Ensure XDebug is installed and configured correctly in phpinfo (See step 1)&lt;/li&gt;
&lt;li&gt;  Make sure the matching port (e.g. 9003) is set in both php.ini and launch.json.&lt;/li&gt;
&lt;li&gt;  Always restart Apache or PHP-FPM after making changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Issue 2: XDebug Not Connecting to VSCode
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Verify the logs in &lt;code&gt;/var/log/xdebug.log&lt;/code&gt; for connection issues.&lt;/li&gt;
&lt;li&gt;  Ensure VSCode is listening for XDebug (&lt;code&gt;F5&lt;/code&gt; in debug mode).&lt;/li&gt;
&lt;li&gt;  Disable other applications using port 9003 (like another debugger).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Issue 3: Path Mapping Problems
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Ensure &lt;code&gt;pathMappings&lt;/code&gt; in &lt;code&gt;launch.json&lt;/code&gt; correctly maps the server path to the local workspace&lt;/li&gt;
&lt;li&gt;  Add &lt;code&gt;$_SERVER['DOCUMENT_ROOT']&lt;/code&gt; in your script to verify paths.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;VSCode and XDebug together make debugging PHP a seamless experience. By following this guide, you should be able to install and configure XDebug properly, and set breakpoints and step through code, and also troubleshoot common debugging issues.&lt;/p&gt;

&lt;p&gt;Finally, if manually tinkering isn't your thing, you can opt for a hassle-free solution like &lt;a href="https://www.mamp.info/" rel="noopener noreferrer"&gt;MAMP&lt;/a&gt; or &lt;a href="https://www.apachefriends.org/" rel="noopener noreferrer"&gt;XAMMP&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy debugging! 🚀&lt;/p&gt;




&lt;h3&gt;
  
  
  About the Author
&lt;/h3&gt;

&lt;p&gt;The author is a full-stack web developer who created SQL-based data analytics and BI reports tool — Querro at &lt;a href="https://querro.io" rel="noopener noreferrer"&gt;querro.io&lt;/a&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>vscode</category>
      <category>querro</category>
      <category>xdebug</category>
    </item>
    <item>
      <title>Simple Hack to Learn 2X Faster</title>
      <dc:creator>PHPControls</dc:creator>
      <pubDate>Sat, 28 Dec 2024 21:10:30 +0000</pubDate>
      <link>https://forem.com/phpcontrols/simple-hack-to-learn-2x-faster-4018</link>
      <guid>https://forem.com/phpcontrols/simple-hack-to-learn-2x-faster-4018</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F5822%2F0%2AVlbdO-UWMhISlIYO" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F5822%2F0%2AVlbdO-UWMhISlIYO" alt="Photo by [Casey Horner](https://unsplash.com/@mischievous_penguins?utm_source=medium&amp;amp;utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral)" width="800" height="713"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While learning React, I couldn’t help but notice how slow the instructor spoke in the recorded lectures. It makes sense being intentionally slow to give time for students to think while absorbing the materials. But after a while, it started to feel like I was waiting for molasses to pour on a chilly day.&lt;/p&gt;

&lt;p&gt;That’s when I discovered the magical speed-up button. Just like that, I was zipping through lectures at 2x speed. It’s like turning your study sessions into an action movie — everything’s faster, more intense, and oddly satisfying.&lt;/p&gt;

&lt;p&gt;It turns out, this isn’t just a life hack — it’s backed by science! According to a &lt;a href="https://www.caltech.edu/about/news/thinking-slowly-the-paradoxical-slowness-of-human-behavior" rel="noopener noreferrer"&gt;Caltech study&lt;/a&gt;, &lt;strong&gt;the human brain is actually &lt;em&gt;faster&lt;/em&gt; than our ears.&lt;/strong&gt; “Multimodal learning” — fancy talk for combining audio and visuals — supercharges how much we can absorb. So, not only are you learning faster, but your brain is also giving you a virtual high-five for being efficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why It Works&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Our brains is capable to process and retain information much faster than the pace of normal speech. Increasing the playback speed while listening, it helps to&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Increases Focus&lt;/strong&gt;: The faster pace reduces the tendency to zone out.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Improves Comprehension&lt;/strong&gt;: Your brain adapts to processing information more efficiently over time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Saves Time&lt;/strong&gt;: Completes a 2-hour lecture in just 1 hour, leaving room for review or practice.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How to Use the Hack Effectively&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;It does take some practice to get to 2x speed-listening. For me, 1.2x is a good comfortable starter pace; 1.5x is efficient and manageable for most content; and 2.0x requires focus but significantly speeds up learning. With time and practice, anyone can adapt and effectively process content at faster speeds.&lt;/p&gt;

&lt;p&gt;I’ve also experimented with going beyond 2x, but it becomes overwhelming and impractical and causes “burn out”, so I don’t recommend.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Start Gradually&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Don’t expect you will be zipping through materials like superman onset. Instead, try at 1.25x or 1.5x speed to get used to faster playback. Gradually increase to 2x speed as your brain adapts to processing quicker speech.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Leverage Closed Captions&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is super important as part of “multimodal learning” to engage our visual sensors to read subtitles to help with clarity, especially for technical or unfamiliar content.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Take Notes Strategically&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use digital tools like &lt;strong&gt;Notion&lt;/strong&gt; or &lt;strong&gt;OneNote&lt;/strong&gt; to jot down key points quickly. Online classes like Udemy and Coursea have note taking tools built-in with video timestamp.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Revisit Critical Sections&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It’s perfectly fine to slow down and walk after a sprint, especially when revisiting difficult sections at a normal speed to ensure thorough understanding.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Free Tools for Enhanced Learning&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Playback Speed Controllers&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Chrome Extensions&lt;/strong&gt;:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://chromewebstore.google.com/detail/video-speed-controller/nffaoalbilbmmfgbnbgppjihopabppdk" rel="noopener noreferrer"&gt;Video Speed Controller&lt;/a&gt;: Allows fine-tuned speed adjustments on most video platforms.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://chromewebstore.google.com/detail/enhancer-for-youtube/ponfpcnoihfmfllpaingbgckeeldkhle?hl=en-US" rel="noopener noreferrer"&gt;Enhancer for YouTube&lt;/a&gt;: Adds playback speed shortcuts for YouTube.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Native Tools&lt;/strong&gt;:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;YouTube, Udemy, Coursera, and similar platforms often have built-in speed controls.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Note-Taking Apps&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.notion.com/" rel="noopener noreferrer"&gt;Notion&lt;/a&gt;, &lt;a href="https://obsidian.md/" rel="noopener noreferrer"&gt;Obsidian&lt;/a&gt;, or &lt;a href="https://evernote.com/" rel="noopener noreferrer"&gt;Evernote&lt;/a&gt;: Great for organizing notes with tags, links, and summaries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://apps.apple.com/us/app/audionote/id369820957" rel="noopener noreferrer"&gt;AudioNote&lt;/a&gt;: Syncs audio or video with your notes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://reclipped.com/" rel="noopener noreferrer"&gt;ReClipped&lt;/a&gt;: Lets you save video highlights and make notes directly linked to timestamps.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Flashcard Tools&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://apps.ankiweb.net/" rel="noopener noreferrer"&gt;Anki&lt;/a&gt; (spaced repetition): Use it to create cards from your notes for active recall.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://quizlet.com/" rel="noopener noreferrer"&gt;Quizlet&lt;/a&gt;: Easier to set up and includes premade decks.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;My Sample Routine for Learning with 2x Speed&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I’ve developed an approach to studying at 2x speed that strikes a balance between efficiency and comprehension. My method combines strategic preparation, active note-taking, and consistent review, allowing me to absorb complex concepts quickly while ensuring a solid understanding.&lt;/p&gt;

&lt;p&gt;Here’s how I’ve made it work for me and how it can work for you too.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Preparation (5 mins)&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Review the syllabus or key concepts for the session.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set a specific goal (e.g., “Understand how recursion works”).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Study (30–60 mins)&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Watch the video at 1.2x — 2x speed, adjust accordingly&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pause to note down key points or rewatch unclear sections.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Review (15 mins)&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Summarize what you learned.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Optional — Create flashcards or a mind map of the main ideas.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Practice (30+ mins)&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Practice exercises or implement the learned concepts in real-world scenarios.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;This simple hack can transform how you learn, making it faster, more efficient, and more engaging. Combine it with proven techniques like active recall and spaced repetition, and you’ll be well on your way to mastering new skills in no time. Try it out, and unlock your potential!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Why Naming Variables Can Distinguish a Good Programmer from a Bad One</title>
      <dc:creator>PHPControls</dc:creator>
      <pubDate>Sat, 23 Nov 2024 04:04:11 +0000</pubDate>
      <link>https://forem.com/phpcontrols/why-naming-variables-can-distinguish-a-good-programmer-from-a-bad-one-3l9b</link>
      <guid>https://forem.com/phpcontrols/why-naming-variables-can-distinguish-a-good-programmer-from-a-bad-one-3l9b</guid>
      <description>&lt;p&gt;While analyzing some old code from a previous project, I stumbled upon variable names that left me scratching my head. Here’s a snippet of what I found:&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;var&lt;/span&gt; &lt;span class="nx"&gt;type&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="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;wfStart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Server Workflow Start&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;yesOrNo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Yes&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;At first glance, these names seemed cryptic at best. After 25 minutes of piecing together the context (aided by poorly written comments), I finally understood what they meant. &lt;/p&gt;

&lt;p&gt;What’s wrong here? To me, it seems the original developer rushed through the implementation, disregarding the importance of meaningful variable names. Instead, they left behind a confusing mess for anyone working on the code later.&lt;/p&gt;

&lt;p&gt;Imagine the difference if the variables were given descriptive, self-explanatory names. Here’s an improved version:&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;var&lt;/span&gt; &lt;span class="nx"&gt;typeCode&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SERVER_WORKFLOW_START&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Server Workflow Start&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;maxLimit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;isConfirmed&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These changes transform the code into something far more understandable. It reflects a clear understanding of the task at hand, good communication of intent.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Importance of Clarity and Communication
&lt;/h3&gt;

&lt;p&gt;Great variable names make it possible to read code almost like a narrative, reducing the need for excessive comments and helping others - and your future self - understand what's going on. Poorly named variables, however, add unnecessary confusion.&lt;/p&gt;

&lt;p&gt;Consider this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;acctWithdrawn&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// number of customers with withdrawn accounts&lt;/span&gt;
&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;ln&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// last name of the current customer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These names require a reader to remember the comments or consult documentation to understand what's going on. With clearer names, this confusion disappears:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt;  &lt;span class="n"&gt;customerWidthdrawnAccount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;customerLastName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These improved names reveal the variables' purposes directly. Code, like any text, should be intuitive and readable.&lt;/p&gt;

&lt;h3&gt;
  
  
  If You Can't Name It, You Don't Understand It
&lt;/h3&gt;

&lt;p&gt;If you struggle to name something, it's likely because you don't fully understand it yet. Naming variables often requires crystal-clear thinking about what the code is trying to accomplish, so unclear names often signal unclear ideas. If you find yourself reaching for vague terms, try asking, "What exactly is this variable representing?" This exercise helps you clarify your logic, which is beneficial not only for naming but for the overall structure of your code.&lt;/p&gt;

&lt;p&gt;To help with this, try using a "descriptive placeholder" name, even if it's excessively long. For instance, instead of trying to name a counter vaguely, use something like &lt;code&gt;numberOfActiveUsersWhereXisTrue&lt;/code&gt;. This will both clarify the variable's purpose for now and signal for future refactoring to find a concise, precise name as the code becomes more defined.&lt;/p&gt;

&lt;p&gt;Here are two JavaScript code examples that demonstrate how to improve variable names for better readability and maintainability:&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 1: Poor Variable Names
&lt;/h3&gt;

&lt;p&gt;In this example, we have ambiguous and non-descriptive names, making it hard to follow the code's intent.&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="c1"&gt;// Poor variable names&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;r&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;res&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;for &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;i&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="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&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;res&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&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="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;100&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;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&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="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;calc&lt;/code&gt; does not indicate what this function actually calculates.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;p&lt;/code&gt; and &lt;code&gt;r&lt;/code&gt; are not descriptive and don’t explain what values they represent.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;res&lt;/code&gt; is unclear and doesn’t indicate that it’s the result of the sum of the array.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Improved Example: Good Variable Names
&lt;/h3&gt;

&lt;p&gt;Let’s rename the variables for clarity so that anyone reading the code can understand its purpose at a glance.&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="c1"&gt;// Improved variable names&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;calculateTotalPrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;basePrice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;discounts&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;totalDiscount&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;for &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;discount&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;discounts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;totalDiscount&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;discount&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="nx"&gt;basePrice&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;totalDiscount&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;100&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;totalPrice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calculateTotalPrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&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="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;calculateTotalPrice&lt;/code&gt; clearly describes the purpose of the function.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;basePrice&lt;/code&gt; and &lt;code&gt;discounts&lt;/code&gt; specify what values are being passed in.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;totalDiscount&lt;/code&gt; makes it clear that it’s the total sum of discounts from the array.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example 2: Using Contextual Variable Names
&lt;/h3&gt;

&lt;p&gt;Let’s look at a second example where the purpose of variables is unclear due to non-descriptive names.&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="c1"&gt;// Poor variable names&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;prsnData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for &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;v&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;a&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;log&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="nx"&gt;d&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="nx"&gt;v&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="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Name&lt;/span&gt;&lt;span class="dl"&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;attributes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;smart&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="s2"&gt;kind&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="s2"&gt;hardworking&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nf"&gt;prsnData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;prsnData&lt;/code&gt; is unclear—does it mean person data or print data?&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;d&lt;/code&gt; and &lt;code&gt;a&lt;/code&gt; don’t describe the values they hold, making the function difficult to follow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Improved Version&lt;/strong&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="c1"&gt;// Improved variable names&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;displayPersonAttributes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;personName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for &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;attribute&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;attributes&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;log&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="nx"&gt;personName&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="nx"&gt;attribute&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;personName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Name&lt;/span&gt;&lt;span class="dl"&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;attributes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;smart&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="s2"&gt;kind&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="s2"&gt;hardworking&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nf"&gt;displayPersonAttributes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;personName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;displayPersonAttributes&lt;/code&gt; is clear and communicates the function’s purpose.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;personName&lt;/code&gt; and &lt;code&gt;attributes&lt;/code&gt; indicate what each parameter represents, making the code easier to understand at a glance. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using meaningful names greatly enhances readability and shows a careful, thoughtful approach to programming.&lt;/p&gt;

&lt;h3&gt;
  
  
  Characteristics of Good Variable Names
&lt;/h3&gt;

&lt;p&gt;While good names vary by context, here are some principles to help make your naming conventions solid:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Be Descriptive but Concise:&lt;/strong&gt; Names should convey purpose. For instance, instead of &lt;code&gt;x&lt;/code&gt;, &lt;code&gt;userAge&lt;/code&gt; is much clearer. At the same time, avoid overly long names that may become cumbersome. Strive for a balance where a variable name is as short as possible while still conveying its purpose. If you have trouble find a good variable name, use aforementioned "descriptive placeholder", and come back to it later.
 &lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Context:&lt;/strong&gt; Variable names should fit the function or class they're in. For instance, a variable in a function handling order data might use &lt;code&gt;orderTotal&lt;/code&gt; or &lt;code&gt;customerID&lt;/code&gt; rather than something generic like &lt;code&gt;data&lt;/code&gt; or &lt;code&gt;num&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Follow Naming Conventions:&lt;/strong&gt; Many languages have specific naming conventions (like camelCase in JavaScript and snake_case in Python). These conventions keep code style consistent and make it easier to read across different projects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Avoid Cryptic Abbreviations:&lt;/strong&gt; Shortening words can lead to confusion, especially if the abbreviation isn't universally recognized. A name like &lt;code&gt;num&lt;/code&gt; may be clear enough, but &lt;code&gt;cnt&lt;/code&gt; could confuse readers who don't know whether it stands for "count," "content," or something else.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Meaningful Prefixes and Suffixes:&lt;/strong&gt; For certain data types or structures, adding a prefix can improve clarity. For example, use &lt;code&gt;listOfUsers&lt;/code&gt; to indicate an array or list, or &lt;code&gt;isEnabled&lt;/code&gt; to show that a variable is a boolean. These prefixes serve as quick cues about the variable's function and type.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Refactoring and Renaming When Necessary
&lt;/h3&gt;

&lt;p&gt;As code evolves, so should variable names. It's common to start with one name and later realize it no longer reflects the variable's purpose accurately. If your variable's name no longer aligns with its function, take the time to rename it. Many modern IDEs such as VSCode support &lt;a href="https://code.visualstudio.com/docs/editor/refactoring" rel="noopener noreferrer"&gt;refactor-&amp;gt;rename&lt;/a&gt; features, which make renaming painless across large codebases. &lt;/p&gt;

&lt;h3&gt;
  
  
  Naming as a Skill to Build Over Time
&lt;/h3&gt;

&lt;p&gt;Variable naming is a skill that improves with practice and attention. Here are a few strategies to strengthen your naming skills:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Practice Mindfulness:&lt;/strong&gt; When choosing a name, take a moment to consider how it reflects the variable's role in the code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Review and Refine:&lt;/strong&gt; As you revisit old code, critique your own variable names and improve them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ask for Feedback:&lt;/strong&gt; Code reviews are invaluable for learning from other perspectives. Peers can offer insights into alternative names that may be clearer.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Naming variables may sound trivial, but it's one of the most telling signs of a programmer's skill and thoughtfulness. A programmer who takes time to name variables thoughtfully is often the one who approaches problems methodically, communicates clearly, and cares about long-term maintainability.&lt;/p&gt;

&lt;h2&gt;
  
  
  About the Author
&lt;/h2&gt;

&lt;p&gt;The author is a veteran web developer who created the popular PHP datagrid tool (&lt;a href="https://phpgrid.com" rel="noopener noreferrer"&gt;phpgrid.com&lt;/a&gt;), harnessing the power of CRUD to make the world a better place — at least for developers looking to simplify their lives!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>coding</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Transform HTML Table into Card View Using Nothing But CSS</title>
      <dc:creator>PHPControls</dc:creator>
      <pubDate>Fri, 25 Oct 2024 03:22:01 +0000</pubDate>
      <link>https://forem.com/phpcontrols/transform-html-table-into-card-view-using-nothing-but-css-17dc</link>
      <guid>https://forem.com/phpcontrols/transform-html-table-into-card-view-using-nothing-but-css-17dc</guid>
      <description>&lt;p&gt;I’d like share a recent experiment that explores how to transform a plain, old-fashioned HTML table into a dynamic card view, going beyond the traditional rows and columns.&lt;/p&gt;

&lt;h1&gt;
  
  
  Start With a Simple HTML Table
&lt;/h1&gt;

&lt;p&gt;Let’s begin with a simple HTML table such as the following.&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;table&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;Company&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;Contact&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;Country&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&amp;gt;&lt;/span&gt;  
        &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;Alfreds Futterkiste&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;Maria Anders&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;Germany&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;tr&amp;gt;&lt;/span&gt;  
        &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;Centro Moctezuma&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;Francisco Chang&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;Mexico&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;tr&amp;gt;&lt;/span&gt;  
        &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;Alfreds &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;Maria &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;Germany&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;tr&amp;gt;&lt;/span&gt;  
        &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;Centro  &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;Francisco Chang&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;Mexico&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;tr&amp;gt;&lt;/span&gt;  
        &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;Alfreds &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;Maria &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;Germany&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;tr&amp;gt;&lt;/span&gt;  
        &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;Centro comercial &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;Francisco &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;Mexico&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;tr&amp;gt;&lt;/span&gt;  
        &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;Alfreds &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;Maria Anders&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;Germany&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;tr&amp;gt;&lt;/span&gt;  
        &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;Centro comercial &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;Francisco &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;Mexico&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It looks like this when rendered in browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa44w9eb8gryy51bhnpjb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa44w9eb8gryy51bhnpjb.png" width="800" height="204"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just another html table&lt;/p&gt;

&lt;p&gt;Nothing fancy.&lt;/p&gt;

&lt;p&gt;By definition, tables consist of rows and columns. How can we transform the traditional rows and columns layout into something more dynamic?&lt;/p&gt;

&lt;h1&gt;
  
  
  Discover the Power of CSS Grid
&lt;/h1&gt;

&lt;p&gt;Tables don’t have to be boring. With a few simple CSS tricks, you can easily transform a traditional HTML table into a sleek list or card view.&lt;/p&gt;

&lt;p&gt;The best part? No JavaScript, just pure CSS!&lt;/p&gt;

&lt;p&gt;CSS grid has been an  &lt;a href="https://www.w3.org/TR/css-grid-3/" rel="noopener noreferrer"&gt;W3C Candidate Recommendation Draft&lt;/a&gt;  since 2007, however, it has been adopted by the recent versions of  &lt;a href="https://caniuse.com/css-grid" rel="noopener noreferrer"&gt;all current major browsers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;CSS grid is designed for both rows and columns, making it ideal for complex layouts such as table. It allows you to manage both horizontal and vertical alignments simultaneously, which gives you much more control than  &lt;a href="https://medium.com/r?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FWeb%2FCSS%2FCSS_grid_layout%2FRelationship_of_grid_layout_with_other_layout_methods" rel="noopener noreferrer"&gt;Flexbox&lt;/a&gt;, which is primarily one-dimensional (row or column).&lt;/p&gt;

&lt;h2&gt;
  
  
  CSS Grid Properties to Use
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt; Use  &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout" rel="noopener noreferrer"&gt;CSS grid layou*&lt;em&gt;t&lt;/em&gt;*&lt;/a&gt;  for &lt;thead&gt; and &lt;/thead&gt;
&lt;tbody&gt;.
&lt;li&gt; Use  &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/display" rel="noopener noreferrer"&gt;CSS display property&lt;/a&gt;  and set all &lt;td&gt; to be block elements


&lt;p&gt;With CSS grid properties, our plain HTML table already magically transforms into a responsive list view, displaying each record neatly in a single column.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;    &lt;span class="nt"&gt;table&lt;/span&gt; &lt;span class="nt"&gt;tbody&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;table&lt;/span&gt; &lt;span class="nt"&gt;thead&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&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="nt"&gt;td&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&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;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxr8xpsz1schlfdqq4bbd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxr8xpsz1schlfdqq4bbd.png" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s looking snazzy but a bit chaotic! Let’s sprinkle on some CSS borders to give each row in our list a little breathing room.&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;table, th, tr {  
  border: 1px solid black;  
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There you go. Check out the new look! Not too shabby for a list view created without a single line of JavaScript magic!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F31wx5d6rl4osb5ssuwoo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F31wx5d6rl4osb5ssuwoo.png" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we got a nice list made from an old-fashioned html table, how do we turn that nice list into a snazzy card view?&lt;/p&gt;

&lt;p&gt;Spoiler alert: just sprinkle on a few more lines of CSS!&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;strong&gt;Transform List into Card View&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Our final card trick to transform table into cards is to use CSS grid property  &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns" rel="noopener noreferrer"&gt;grid-template-columns&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;    &lt;span class="nt"&gt;table&lt;/span&gt; &lt;span class="nt"&gt;tbody&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
      &lt;span class="py"&gt;grid-template-columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;fr&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;p&gt;&lt;code&gt;grid-template-columns&lt;/code&gt;  is a CSS property used in the CSS Grid layout to define the structure of the grid's columns. It specifies the number of columns, their widths, and how the space within the grid is divided.&lt;/p&gt;

&lt;p&gt;With the  &lt;code&gt;repeat()&lt;/code&gt;  function, the first parameter lets us decide how many columns we want—let’s say 4, because who doesn’t love a nice round number? The second parameter tells those columns how big to be—1fr, or one fraction of the available space. It’s like giving your columns a little pep talk: 'You all get an equal slice of the space pie!'&lt;/p&gt;
&lt;h2&gt;
  
  
  Our final card view
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs9uvpytypphrwoxm6ppj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs9uvpytypphrwoxm6ppj.png" width="800" height="309"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Take a moment to explore the code and see the results for yourself over on CodePen. It’s the perfect place to experiment and play around with CSS grid transformations. You may even discover some fun surprises along the way.&lt;/p&gt;

&lt;p&gt;Keep in mind that CSS Grid is also responsive, providing developers with enhanced control over how layouts adjust and reflow across various screen sizes and devices.&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;strong&gt;Optional: Adding data-label to card view&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;While the card view is visually appealing, it lacks the clarity of column information, leaving users to guess the data represented in each card.&lt;/p&gt;

&lt;p&gt;By incorporating a touch of JavaScript, we can seamlessly add data labels for each column, enhancing the association between the labels and their corresponding cells.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Store each column header to array  &lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;labels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;  
&lt;span class="nf"&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;table&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;thead th&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nx"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;  
&lt;span class="p"&gt;});&lt;/span&gt;  

&lt;span class="c1"&gt;// Add data-label attribute to each cell  &lt;/span&gt;
&lt;span class="nf"&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;table).find(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;tbody&lt;/span&gt; &lt;span class="nx"&gt;tr&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;).each(function() {  
    $(this).find(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;td&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;).each(function(column) {  
        $(this).attr(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;, labels[column]);  
    });  
});
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;The same code above using ES6 vanilla javascript without jQuery&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Store each column header to array&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;labels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;table thead th&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;th&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;th&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// Add data-label attribute to each cell&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;table tbody tr&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tr&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;td&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;td&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;column&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="nx"&gt;td&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-label&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;column&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;p&gt;It now looks like this&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc22p129ir308ex81p8ja.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc22p129ir308ex81p8ja.png" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://demo.phpcontrols.com/lib/phpGrid/examples/card_view.php" rel="noopener noreferrer"&gt;&lt;strong&gt;Demo&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s nothing like the html table that we started with. With CSS Grid, the layout options are endless because it allows for full control over both rows and columns in a two-dimensional space.&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;This tutorial only scratches the surface of the iceberg. You can easily create more responsive layouts, overlap elements, span items across multiple rows or columns, and adjust grid areas dynamically, making it highly versatile for various layout needs.&lt;/p&gt;

&lt;p&gt;Happy gridding!&lt;/p&gt;
&lt;h2&gt;
  
  
  About the Author
&lt;/h2&gt;

&lt;p&gt;The author is a veteran web developer who created the popular PHP datagrid tool (&lt;a href="https://phpgrid.com/" rel="noopener noreferrer"&gt;phpgrid.com&lt;/a&gt;), harnessing the power of CRUD to make the world a better place — at least for developers looking to simplify their lives!&lt;/p&gt;
&lt;/td&gt;
&lt;/li&gt;
&lt;/tbody&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>datagrid</category>
      <category>css</category>
      <category>html</category>
      <category>php</category>
    </item>
  </channel>
</rss>
