<?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: Martin Kordas</title>
    <description>The latest articles on DEV Community by Martin Kordas (@martinkordas).</description>
    <link>https://dev.to/martinkordas</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%2F579942%2F2d94ee54-8217-4fce-9497-87c54c0ad169.png</url>
      <title>DEV Community: Martin Kordas</title>
      <link>https://dev.to/martinkordas</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/martinkordas"/>
    <language>en</language>
    <item>
      <title>7 modern and practical MySQL/MariaDB features you should know and use</title>
      <dc:creator>Martin Kordas</dc:creator>
      <pubDate>Wed, 08 Dec 2021 09:46:14 +0000</pubDate>
      <link>https://dev.to/martinkordas/practical-modern-mysqlmariadb-features-you-should-know-and-use-2jmi</link>
      <guid>https://dev.to/martinkordas/practical-modern-mysqlmariadb-features-you-should-know-and-use-2jmi</guid>
      <description>&lt;p&gt;When programming we always tend to look up new interesting syntax features of our main programming language. With SQL database systems systems however we are not so eager, although we use use SQL almost every day. MySQL and MariaDB are constantly evolving and some of the newly added features can help you a lot. Unfortunately the most useful things in changelogs are often hidden among other not so important changes, like storage engines optimizations, adding specific new data types or changing the behaviour of certain configuration variables.&lt;/p&gt;

&lt;p&gt;This short list include &lt;strong&gt;7 important new functionalities&lt;/strong&gt; which make your life simpler. For practical examples, please see provided links. Since MySQL and MariaDB have diverted from each other, I will link each of them individually. Some functionalities are available in MariaDB only.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;WITH&lt;/code&gt; clause (common table expressions)&lt;/strong&gt; (since &lt;a href="https://dev.mysql.com/doc/refman/8.0/en/with.html"&gt;MySQL 8.0&lt;/a&gt;, &lt;a href="https://mariadb.com/kb/en/with/"&gt;MariaDB 10.2.1&lt;/a&gt;): By using &lt;code&gt;WITH&lt;/code&gt; you can define derived tables at the beginning of your query. This way subqueries are not nested in the main query, which makes the whole query much more readable. Moreover, advanced &lt;code&gt;WITH RECURSIVE&lt;/code&gt; clause lets you define recursive algorithms for processing table values (can be used for sequences generation, hierarchical data traversal etc.). See &lt;a href="https://dev.mysql.com/doc/refman/8.0/en/with.html#common-table-expressions-recursive"&gt;MySQL ref&lt;/a&gt; for detailed explanation and examples.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;OVER&lt;/code&gt; clause and window functions&lt;/strong&gt; (since &lt;a href="https://dev.mysql.com/doc/refman/8.0/en/window-functions-usage.html"&gt;MySQL 8.0&lt;/a&gt;, &lt;a href="https://mariadb.com/kb/en/window-functions-overview/"&gt;MariaDB 10.2&lt;/a&gt;): Similarly to &lt;code&gt;GROUP BY&lt;/code&gt;, &lt;code&gt;OVER&lt;/code&gt; clause enables you to define a groups of rows (&lt;em&gt;window&lt;/em&gt;) and work with column values in each group using &lt;em&gt;window functions&lt;/em&gt;. In constrast to &lt;code&gt;GROUP BY&lt;/code&gt;, the resulting set of rows remains the same, i.e. rows are not grouped in the result. This way you can use classical aggregate functions like &lt;code&gt;SUM()&lt;/code&gt; or &lt;code&gt;AVG()&lt;/code&gt; on groups of rows (e.g. groups of comments belonging to the same blog post) and display the agregate function's return value in a column (e.g. sum of comment's likes numbers), but without actually grouping the results. Using specialized window functions (&lt;a href="https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html"&gt;MySQL ref&lt;/a&gt;, &lt;a href="https://mariadb.com/kb/en/window-functions/"&gt;MariaDB ref&lt;/a&gt;) you can do even more, like obtain first/last column value in a group, obtain number of row in a group or obtain previous/following value in a group. The latter gives you exceptional ability to compare values of adjacent rows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;INTERSECT&lt;/code&gt;/&lt;code&gt;EXCEPT&lt;/code&gt;&lt;/strong&gt; (since MariaDB 10.3 - &lt;a href="https://mariadb.com/kb/en/intersect/"&gt;INTERSECT&lt;/a&gt;, &lt;a href="https://mariadb.com/kb/en/except/"&gt;EXCEPT&lt;/a&gt;): In the past intersect and except (difference) operations needed to be done manually by &lt;code&gt;JOIN&lt;/code&gt;ing tables and filtering rows. Now you can use more readable &lt;code&gt;INTERSECT&lt;/code&gt; and &lt;code&gt;EXCEPT&lt;/code&gt; operators.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;VALUES&lt;/code&gt; statement (table values constructor)&lt;/strong&gt; (since &lt;a href="https://dev.mysql.com/doc/refman/8.0/en/values.html"&gt;MySQL 8.0&lt;/a&gt;, &lt;a href="https://mariadb.com/kb/en/table-value-constructors/"&gt;MariaDB 10.3.3&lt;/a&gt;): This practical feature lets you create a table on the fly using literal row values, e.g. &lt;code&gt;SELECT * FROM table UNION VALUES (10, 20), (30, 40)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;CREATE SEQUENCE&lt;/code&gt; statement&lt;/strong&gt; (since &lt;a href="https://mariadb.com/kb/en/create-sequence/"&gt;MariaDB 10.3&lt;/a&gt;): While being standard for a long time in many other database systems, MariaDB has adopted sequences recently. They allow you to define a custom way of auto incrementing column values (e.g. incrementing it by addition of 2 instead of 1 etc.).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;JSON&lt;/code&gt; data type&lt;/strong&gt; (since &lt;a href="https://dev.mysql.com/doc/refman/8.0/en/json.html"&gt;MySQL 5.7&lt;/a&gt;, &lt;a href="https://mariadb.com/kb/en/json-data-type/"&gt;MariaDB 10.2.7&lt;/a&gt;): In an effort to bring SQL databases closer to noSQL world, RDBMS servers are trying to facilitate JSON data handling. This enables you to combine solid relation database schema with schemaless JSON fields, which are similar to document-oriented databases. You can add or remove attributes from your JSON data without any &lt;code&gt;ALTER TABLE&lt;/code&gt; query. Columns using  &lt;code&gt;JSON&lt;/code&gt; data type and can be manipulated as string or using special &lt;code&gt;JSON_*()&lt;/code&gt; functions. Database server will check validity of submitted JSON string, will be able to read its content using &lt;code&gt;JSON_*()&lt;/code&gt; functions with &lt;em&gt;JSONPath&lt;/em&gt; syntax and it is even possible to put indexes on individual JSON attributes. MySQL in addition offers operators &lt;code&gt;-&amp;gt;&lt;/code&gt; and &lt;code&gt;-&amp;gt;&amp;gt;&lt;/code&gt; to access JSON column content. Implementations of JSON support in MySQL and MariaDB differ. For MySQL see &lt;a href="https://dev.mysql.com/doc/refman/8.0/en/json.html"&gt;JSON Data Type overview&lt;/a&gt;, for MariaDB see &lt;a href="https://dzone.com/articles/json-with-mariadb-platform-what-is-json-and-why-us"&gt;JSON With MariaDB platform&lt;/a&gt; article.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Temporal tables&lt;/strong&gt; (since &lt;a href="https://mariadb.com/kb/en/temporal-tables/"&gt;MariaDB 10.3.4/10.4.3&lt;/a&gt;): Several functionalities which help you to read and write data within versioned tables (i.e. tables with records storing date and time ranges). You can easily query rows data valid in certain time point or time span. When updating or deleting data for specified date range, rows are automatically split, shrunk or deleted. This part would be very hard to implement on the application side, so why not to use native database server functionality?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the end, I will mention some older but useful features which are not commonly known:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Null-safe equal operator &lt;code&gt;&amp;lt;=&amp;gt;&lt;/code&gt;&lt;/strong&gt; (&lt;a href="https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_equal-to"&gt;MySQL ref&lt;/a&gt;, &lt;a href="https://mariadb.com/kb/en/null-safe-equal/"&gt;MariaDB ref&lt;/a&gt;): Allows to easily compare nullable columns (without the need to test if column &lt;code&gt;IS NULL&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;+&lt;/code&gt;/&lt;code&gt;-&lt;/code&gt; operators for date/datetime manipulation&lt;/strong&gt;: Simply put, you can use &lt;code&gt;date_column + interval 1 DAY&lt;/code&gt; instead of &lt;code&gt;DATE_ADD(date_column, INTERVAL 1 DAY)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Row subqueries&lt;/strong&gt; (&lt;a href="https://dev.mysql.com/doc/refman/8.0/en/row-subqueries.html"&gt;MySQL ref&lt;/a&gt;, &lt;a href="https://mariadb.com/kb/en/subqueries-row-subqueries/"&gt;MariaDB ref&lt;/a&gt;): When using subqueries in the &lt;code&gt;WHERE&lt;/code&gt; clause, more then 1 value can be returned from the subquery and compared, e.g. &lt;code&gt;WHERE (name,age) IN (SELECT name, age FROM customer)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;REPLACE&lt;/code&gt; statement&lt;/strong&gt; (&lt;a href="https://dev.mysql.com/doc/refman/8.0/en/replace.html"&gt;MySQL ref&lt;/a&gt;, &lt;a href="https://mariadb.com/kb/en/replace/"&gt;MariaDB ref&lt;/a&gt;): Acts like &lt;code&gt;INSERT&lt;/code&gt; except the case when a row with the same primary key value already exists in the database. In such situation &lt;code&gt;REPLACE&lt;/code&gt; will delete the existing row before inserting new one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;#&lt;/code&gt;/&lt;code&gt;--&lt;/code&gt; comments syntax&lt;/strong&gt;: Putting a hash or two dashes and a whitespace into SQL will mark as comment everything to the end of the current line. It is more practical than classical pair &lt;code&gt;/* ... */&lt;/code&gt; comments syntax.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope these tips will help you to write more readable and powerful SQL queries.&lt;/p&gt;

</description>
      <category>mysql</category>
      <category>sql</category>
      <category>database</category>
    </item>
    <item>
      <title>Revealing Module design pattern and when (not) to use it in PHP</title>
      <dc:creator>Martin Kordas</dc:creator>
      <pubDate>Thu, 11 Nov 2021 00:10:11 +0000</pubDate>
      <link>https://dev.to/martinkordas/revealing-module-design-pattern-and-when-not-to-use-it-in-php-4b6d</link>
      <guid>https://dev.to/martinkordas/revealing-module-design-pattern-and-when-not-to-use-it-in-php-4b6d</guid>
      <description>&lt;h3&gt;
  
  
  Originated in Javascript...
&lt;/h3&gt;

&lt;p&gt;One of the most common design patterns used in JavaScript is &lt;strong&gt;Revealing Module&lt;/strong&gt;. Since JavaScript initially didn't have classic Java-like OOP system, Revealing Module concept was used instead to create simple objects and implement private-like object properties. Revealing Module also fits well into functional nature of JavaScript. (You can see example implementation of Revealing Module in JS on &lt;a href="https://gist.github.com/zcaceres/bb0eec99c02dda6aac0e041d0d4d7bf2"&gt;GitHub Gist&lt;/a&gt;.)&lt;/p&gt;

&lt;h3&gt;
  
  
  ..but can also be used in PHP
&lt;/h3&gt;

&lt;p&gt;Since PHP includes OOP for very long time, it is quite &lt;strong&gt;non-idiomatic&lt;/strong&gt; to replace classical OOP object handling with functional alternatives like Revealing Module. However thanks to great support of &lt;a href="https://www.php.net/manual/en/functions.anonymous.php"&gt;anonymous functions&lt;/a&gt; in PHP it is very straightforward to implement it. You can do it as an exercise to dig deeper into functional PHP programming or you can use it in your mainly procedural codebase which you don't want to mix with OOP paradigm, but still want to use some object-like approach.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: rectangle object
&lt;/h3&gt;

&lt;p&gt;For easier explanation, I will start with practical example - using Revealing Module in PHP to implement simple "rectangle" object. You will easily understand that &lt;code&gt;$rectangle&lt;/code&gt; is a constructor function, which returns &lt;code&gt;$rectangle0&lt;/code&gt; - an array representing newly created object instance with public properties and functions on it. Local variables inside &lt;code&gt;$rectangle&lt;/code&gt; functions on the other hand act like private members.&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;$rectangle&lt;/span&gt; &lt;span class="o"&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;int&lt;/span&gt; &lt;span class="nv"&gt;$a&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;$b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;$name&lt;/span&gt;             &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"rectangle"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;$is_square&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$b&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="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nv"&gt;$rectangle0&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s2"&gt;"get_area"&lt;/span&gt;      &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$b&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="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s2"&gt;"get_perimeter"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$is_square&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="nv"&gt;$is_square&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="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nv"&gt;$a&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="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s2"&gt;"set_a"&lt;/span&gt;         &lt;span class="o"&gt;=&amp;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;int&lt;/span&gt; &lt;span class="nv"&gt;$a1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$a1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s2"&gt;"set_b"&lt;/span&gt;         &lt;span class="o"&gt;=&amp;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;int&lt;/span&gt; &lt;span class="nv"&gt;$b1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$b1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s2"&gt;"get_name"&lt;/span&gt;      &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"to_string"&lt;/span&gt;     &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$rectangle0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$b&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;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"%s: %s x %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$rectangle0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"get_name"&lt;/span&gt;&lt;span class="p"&gt;](),&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$b&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;return&lt;/span&gt; &lt;span class="nv"&gt;$rectangle0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nv"&gt;$rectangle1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$rectangle&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="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$rectangle1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"get_perimeter"&lt;/span&gt;&lt;span class="p"&gt;]();&lt;/span&gt;   &lt;span class="c1"&gt;// result: 10&lt;/span&gt;
&lt;span class="nv"&gt;$rectangle1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"get_area"&lt;/span&gt;&lt;span class="p"&gt;]();&lt;/span&gt;        &lt;span class="c1"&gt;// result: 6&lt;/span&gt;
&lt;span class="nv"&gt;$rectangle2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$rectangle&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="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$rectangle2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"get_perimeter"&lt;/span&gt;&lt;span class="p"&gt;]();&lt;/span&gt;   &lt;span class="c1"&gt;// result: 16&lt;/span&gt;
&lt;span class="nv"&gt;$rectangle2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"set_a"&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="nv"&gt;$rectangle2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"get_perimeter"&lt;/span&gt;&lt;span class="p"&gt;]();&lt;/span&gt;   &lt;span class="c1"&gt;// result: 18&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  General pattern description
&lt;/h3&gt;

&lt;p&gt;More general scheme of Revealing Module pattern with explanation of certain parts in comments looks as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 1) $obj is function acting as CONSTRUCTOR&lt;/span&gt;
&lt;span class="c1"&gt;//  - passed parameters $param1, $param2 can be later accessed by any private or public properties/functions defined in constructor&lt;/span&gt;
&lt;span class="nv"&gt;$obj&lt;/span&gt; &lt;span class="o"&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;$param1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$param2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// 2) PRIVATE properties/functions are implemented as local variables&lt;/span&gt;
  &lt;span class="nv"&gt;$private_prop1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;$private_func1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$obj0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$private_prop1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$param1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$private_func1&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 function $private_func1 can access other private properties/functions&lt;/span&gt;
    &lt;span class="nv"&gt;$private_prop1&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// private function $private_func1 can access public properties/functions via $obj0 reference (see below)&lt;/span&gt;
    &lt;span class="nv"&gt;$obj0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"public_prop1"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nv"&gt;$param1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// function $private_func1 is also able to call itself recursively via $private_func1 reference&lt;/span&gt;
    &lt;span class="k"&gt;if&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="nv"&gt;$private_func1&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// 3) PUBLIC properties/functions are implemented as values in $obj0 array&lt;/span&gt;
  &lt;span class="c1"&gt;//  - $obj0 itself represents newly created object instance and is returned from constructor function&lt;/span&gt;
  &lt;span class="nv"&gt;$obj0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s2"&gt;"public_prop1"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"public_func1"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$obj0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$private_func1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$param2&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 function public_func1 can access other public properties/functions via $obj0 reference&lt;/span&gt;
      &lt;span class="nv"&gt;$obj0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"public_prop1"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nv"&gt;$param2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="c1"&gt;// public function public_func1 can access private properties/functions&lt;/span&gt;
      &lt;span class="nv"&gt;$private_func1&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;return&lt;/span&gt; &lt;span class="nv"&gt;$obj0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="c1"&gt;// 5) INSTANCE $obj1 will be created by calling constructor function $obj&lt;/span&gt;
&lt;span class="nv"&gt;$obj1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$obj&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;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$obj1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"public_func1"&lt;/span&gt;&lt;span class="p"&gt;]();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This snippet comprises roughly everything you need to know about Revealing Module.&lt;/p&gt;

&lt;p&gt;When using Revealing Module in PHP you should specifically be careful about &lt;code&gt;use (...)&lt;/code&gt; construct, which  needs to declare all variables from the outer scope that your function needs to use. Especially ensure you declare variables by reference (&lt;code&gt;use (&amp;amp;$private_prop1)&lt;/code&gt;) instead of by value (&lt;code&gt;use ($private_prop1)&lt;/code&gt;), otherwise the variable value in the inner scope will not match future changes of the variable in outer scope and it also won't be possible to edit the variable from the inner scope.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Finally, it would be very interesting to look at pros and cons of Revealing Module approach in comparison with traditional PHP OOP.&lt;/p&gt;

&lt;h4&gt;
  
  
  Advantages
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Revealing Module &lt;strong&gt;fits well into procedural codebase&lt;/strong&gt;, in case you don't want to mix it with OOP. It also doesn't require any knowledge of OOP programming.&lt;/li&gt;
&lt;li&gt;It is suitable for &lt;strong&gt;simple ad-hoc objects&lt;/strong&gt; you create inside of other existing module or script. In such cases you don't necessarily want to create full OOP class in separate file. Revealing Module constructors can be created in the middle of existing code, even inside loops (constructor function redefinition doesn't imply any error).&lt;/li&gt;
&lt;li&gt;Object instance is implemented as an array and is quite &lt;strong&gt;flexible&lt;/strong&gt;. You can add/delete public properties and functions, sort them and build nested structures from them (e.g. &lt;code&gt;$obj1["functions_group1"]["function1"]();&lt;/code&gt;: member function &lt;code&gt;function1&lt;/code&gt; has been placed into  &lt;code&gt;functions_group1&lt;/code&gt;, which is just a nested array of functions).&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Constructor function is standard variable (&lt;code&gt;Closure&lt;/code&gt; object) and &lt;strong&gt;can be manipulated easily&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can store it in another variable, return it from a function or pass it as a parameter:
&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$rectangle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$rectangle&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="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$rectangle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;ul&gt;
&lt;li&gt;Standard OOP class on the other hand is not a variable and you can pass it as a parameter only using its name obtained from &lt;code&gt;::class&lt;/code&gt; constant:
&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$className&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="nv"&gt;$className&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="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Rectangle&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;/code&gt;&lt;/pre&gt;




&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Disadvantages
&lt;/h4&gt;

&lt;p&gt;This list is very extensive, that's why you should use Revealing Module only sparingly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Inheritance, cloning and serialization&lt;/strong&gt; of Revealing Module objects are not possible. (Especially lack of inheritance is quite painful, because it is strong mechanism of code reuse.) Determining object type using &lt;code&gt;instanceof&lt;/code&gt; or &lt;code&gt;get_class()&lt;/code&gt; is not possible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type hinting&lt;/strong&gt; of private or public object properties and functions is not possible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IDE support&lt;/strong&gt; is poor. You probably will not get any autocomplete for public object properties and functions, because they are implemented as simple array values. You cannot document member properties and functions with PHPDoc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Autoloading&lt;/strong&gt; is not possible. If your constructor function is located in a separate file, you will need to &lt;code&gt;include&lt;/code&gt; it manually.&lt;/li&gt;
&lt;li&gt;Code structure consisting of private and public members is not as optically clear as with classic OOP. Necessity to put so many variables into &lt;code&gt;use (...)&lt;/code&gt; construct is annoying and causes code bloat.&lt;/li&gt;
&lt;li&gt;Object instances are simple arrays and, as such, are &lt;strong&gt;passed by value&lt;/strong&gt; by default. It is undesirable, because we are used to objects being passed by reference.&lt;/li&gt;
&lt;li&gt;It is not possible to implement &lt;strong&gt;static object properties and functions&lt;/strong&gt;. You always need to create instance first and call instance properties and functions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope this article has inspired you to use functional programming in PHP more frequently, or even try out Revealing Module pattern in PHP or any other functional-ready language. For common work on PHP backend, you should probably stick to traditional OOP approach.&lt;/p&gt;

</description>
      <category>php</category>
      <category>functional</category>
      <category>design</category>
      <category>oop</category>
    </item>
    <item>
      <title>PHP global functions: how they affect code extensibility, testability and modularity</title>
      <dc:creator>Martin Kordas</dc:creator>
      <pubDate>Wed, 29 Sep 2021 21:36:23 +0000</pubDate>
      <link>https://dev.to/martinkordas/php-global-functions-how-they-affect-code-extensibility-testability-and-modularity-54h7</link>
      <guid>https://dev.to/martinkordas/php-global-functions-how-they-affect-code-extensibility-testability-and-modularity-54h7</guid>
      <description>&lt;p&gt;We all have been told not to use &lt;strong&gt;global variables&lt;/strong&gt;, as they can be modified and read from whatever part of code, which causes confusion and errors. Using &lt;strong&gt;global functions&lt;/strong&gt; by contrast is quite common, but can be problematic too.&lt;/p&gt;

&lt;p&gt;We will discuss issues of global function calls on a simple &lt;code&gt;Notification&lt;/code&gt; class, which calls global function &lt;code&gt;logMessage()&lt;/code&gt; internally.&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$isRead&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="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;markAsRead&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;isRead&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="nf"&gt;logMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'article was marked as read'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Issue 1: Extensibility
&lt;/h2&gt;

&lt;p&gt;Function &lt;code&gt;logMessage()&lt;/code&gt; probably logs given message into a file. The problem is that the call is hardcoded into the function &lt;code&gt;markAsRead()&lt;/code&gt; and cannot be changed externally, which violates the &lt;a href="https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle"&gt;&lt;strong&gt;Open-closed principle&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Common solution is to use an &lt;strong&gt;object&lt;/strong&gt; (not function) for the purpose of logging and pass it to the &lt;code&gt;Notification&lt;/code&gt; class constructor. This technique is called &lt;a href="https://en.wikipedia.org/wiki/Dependency_injection"&gt;&lt;strong&gt;Dependency-injection&lt;/strong&gt;&lt;/a&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$isRead&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="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$logger&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="nv"&gt;$logger&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;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$logger&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;markAsRead&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;isRead&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="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;logMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'article was marked as read'&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 way is the logging logic separated into a distinct object &lt;code&gt;$logger&lt;/code&gt;, which is injected into the &lt;code&gt;Notification&lt;/code&gt; class externally. It means we can affect the logging logic from the outside (e.g. we can use logger object which logs messages to a file or use another one which logs to database etc.)&lt;/p&gt;

&lt;p&gt;(Alternatively it is possible to use &lt;a href="https://en.wikipedia.org/wiki/Factory_method_pattern"&gt;&lt;strong&gt;Factory method pattern&lt;/strong&gt;&lt;/a&gt;. In that case, we would pass &lt;strong&gt;factory object&lt;/strong&gt; (not the actual logger object) to the &lt;code&gt;Notification&lt;/code&gt; class constructor and the logger object would be created by &lt;code&gt;Notification&lt;/code&gt; class itself calling a factory object method.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Issue 2: Testability
&lt;/h2&gt;

&lt;p&gt;When writing unit tests, we often need to &lt;strong&gt;change behaviour of the tested class slightly&lt;/strong&gt; (e.g. we want to turn off logging completely during tests instead of usual logging into a file).&lt;/p&gt;

&lt;p&gt;Again, with global function it is impossible to change logging behaviour from the outside of the class. By contrast, the above mentioned solution with &lt;strong&gt;dependency injection&lt;/strong&gt; provides possibility to pass custom logger object which will silently ignore all log messages, which is the desired behaviour.&lt;/p&gt;

&lt;h2&gt;
  
  
  Issue 3: Modularity
&lt;/h2&gt;

&lt;p&gt;Modularity is closely related to testability. We need to test separate code parts which ideally do &lt;em&gt;not&lt;/em&gt; interact with each other (see also &lt;a href="https://en.wikipedia.org/wiki/Single-responsibility_principle"&gt;&lt;strong&gt;Single-responsibility principle&lt;/strong&gt;&lt;/a&gt;. This way only are we able to find errors in the tested module itself without mixing them with errors from other interacting modules.&lt;/p&gt;

&lt;p&gt;Solution with &lt;strong&gt;dependency injection&lt;/strong&gt; described above gives us opportunity to choose custom logger object. With the help of testing framework such as &lt;a href="https://phpunit.de/"&gt;PHPUnit&lt;/a&gt; we can create &lt;strong&gt;stub&lt;/strong&gt; object instead of regular logger object, which allows us to freely redefine or suppress object functionality for purposes of the test and also watch which methods on the logger object has been called from inside of tested module (&lt;strong&gt;mocking&lt;/strong&gt;). Neither of these features can be achieved when implementing logging with a global function.&lt;/p&gt;

&lt;p&gt;Last but not least, modularity gives you knowledge about what other modules your current module uses (E.g. with dependency injection, you can just look on class constructor's parameters. They represent injected objects and this objects in turn represent injected functionality from other modules.) With this knowledge of module dependencies you can more easily extract your code and use it in another project, as you know which other modules it depends on and which of them you therefore have to extract as well.&lt;/p&gt;

&lt;p&gt;There is one alternative solution of modularity using &lt;strong&gt;namespaced global functions&lt;/strong&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;use&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;utils\logging\filesystem\logMessage&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;Notification&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$isRead&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="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;markAsRead&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;isRead&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="nf"&gt;logMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'article was marked as read'&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;Enclosing functions in namespaces gives you some modularity per se. Moreover, each called namespaced function is usually mentioned with &lt;code&gt;use&lt;/code&gt; operator statement in the beginning of the file. Thus you can more easily overview which functions from other modules are called from inside your class. You can also change the namespace (for example to &lt;code&gt;\utils\logging\database\logMessage&lt;/code&gt;) and thus change logging behaviour as well, but this change &lt;em&gt;cannot&lt;/em&gt; be made on runtime, because doing the change requires you to modify the source code. (In contrast, with dependency injection the change &lt;em&gt;can&lt;/em&gt; be done on runtime, because the changed behaviour is represented by runtime injected object.)&lt;/p&gt;

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

&lt;p&gt;Given the limitations of global function calls, &lt;strong&gt;you should generally avoid them when possible&lt;/strong&gt; (at least if you work on OOP project) or use them only in several cases when they become handy, e.g.:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;very &lt;strong&gt;frequently used&lt;/strong&gt; functions (calling global functions is much shorter in code than instancing a class and calling a class method)&lt;/li&gt;
&lt;li&gt;functions with &lt;strong&gt;unimportant&lt;/strong&gt; functionality (debugging functions, shorthand functions which probably only call some object method)&lt;/li&gt;
&lt;li&gt;very &lt;strong&gt;widely used&lt;/strong&gt; functions (used almost in every project module)&lt;/li&gt;
&lt;li&gt;functions whose logic is &lt;em&gt;not&lt;/em&gt; meant to be modified or mocked (e.g. during unit tests, see above)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;platform functions&lt;/strong&gt; - built-in PHP functionality is mostly implemented as global functions (&lt;code&gt;array_push()&lt;/code&gt;, &lt;code&gt;strlen()&lt;/code&gt; etc.) - we usually don't use objects and dependency injection for basic built-in functionality like string or array manipulation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See also &lt;a href="https://laravel.com/docs/8.x/helpers#miscellaneous-method-list"&gt;Laravel Miscellaneous functions list&lt;/a&gt; as an example of what type of functions the framework defines globally (as opposed to object methods which make up the majority in Laravel).&lt;/p&gt;

</description>
      <category>php</category>
      <category>testing</category>
      <category>oop</category>
      <category>functional</category>
    </item>
    <item>
      <title>Speed up switching between opened windows using Autohotkey shortcuts</title>
      <dc:creator>Martin Kordas</dc:creator>
      <pubDate>Tue, 21 Sep 2021 15:51:33 +0000</pubDate>
      <link>https://dev.to/martinkordas/speed-up-switching-between-opened-windows-using-autohotkey-shortcuts-4fb1</link>
      <guid>https://dev.to/martinkordas/speed-up-switching-between-opened-windows-using-autohotkey-shortcuts-4fb1</guid>
      <description>&lt;p&gt;Usually our OS runs quite many application at one time and it could be quite hard not to get lost in so many opened windows. If you are using Windows, you usually have several built-in possibilities how to switch between open apps.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select an app from taskbar.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;Alt+Tab&lt;/code&gt; or &lt;code&gt;Win+Tab&lt;/code&gt; shortcut to switch the app. (Least recently used apps are displayed first, which helps your orientation. You can also use arrow keys to navigate between suggested apps and &lt;code&gt;Delete&lt;/code&gt; to close an app.)&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;Win+&amp;lt;n&amp;gt;&lt;/code&gt; shortcut to open an app, whose icon is the &lt;code&gt;n&lt;/code&gt;th icon on the taskbar. (You usually have several apps pinned to the taskbar, so their position is unchanging and therefore you remember their hotkey. For example, if you have web browser pinned as a first app on your taskbar, you regularly use &lt;code&gt;Win+1&lt;/code&gt; shortcut to open browser window. If the app doesn't run at all, OS will run it.)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Using &lt;code&gt;Win+&amp;lt;n&amp;gt;&lt;/code&gt; shortcut saves me much time as I don't have to search between opened windows, I just use one exact hotkey instead and the window gets displayed. The problem is that it is possible to use this hotkey only for 10 apps (corresponding to 0-9 keys on your keyboard).&lt;/p&gt;

&lt;p&gt;For this reason I installed &lt;strong&gt;&lt;a href="https://www.autohotkey.com/"&gt;Autohotkey&lt;/a&gt; program&lt;/strong&gt; and created a simple script which shows an app based on its window title text. I always use &lt;code&gt;Win+Shift+?&lt;/code&gt; shortcut (&lt;code&gt;#&lt;/code&gt; means &lt;code&gt;Win&lt;/code&gt;, &lt;code&gt;+&lt;/code&gt; means &lt;code&gt;Shift&lt;/code&gt; in Autohotkey scripts). With the script running, Visual Studio window shows up upon pressing &lt;code&gt;Win+Shift+V&lt;/code&gt;, Postman shows up upon pressing &lt;code&gt;Win+Shift+P&lt;/code&gt; and so on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SetTitleMatchMode, Regex
SetTitleMatchMode, Slow

#+v::
WinActivate, .*Visual Studio
return 

#+p::
WinActivate, Postman
return

#+o::
WinActivate, .*LibreOffice
return

#+c::
WinActivate, .*Calc
return
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you save the script with &lt;code&gt;.ahk&lt;/code&gt; extension you can run it manually by double clicking it. Alternatively you can place it into your startup folder (&lt;code&gt;%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup&lt;/code&gt;) so as it will run automatically every time you use your computer.&lt;/p&gt;

&lt;p&gt;Now you can switch to almost every running app so fast with just one keyboard shortcut.&lt;/p&gt;

&lt;p&gt;You can do many other useful things with Autohotkey, like remapping keys you lack on your current physical keyboard or creating shortcuts for multimedia features (start/resume playing, volume up/down...), all of this achieved with standard keyboard layout without the need to buy specialized keyboard with additional keys.&lt;/p&gt;

</description>
      <category>autohotkey</category>
      <category>windows</category>
      <category>script</category>
    </item>
    <item>
      <title>How to properly store and print plaintext strings</title>
      <dc:creator>Martin Kordas</dc:creator>
      <pubDate>Sun, 14 Mar 2021 23:19:04 +0000</pubDate>
      <link>https://dev.to/martinkordas/how-to-properly-store-and-print-plaintext-strings-41i3</link>
      <guid>https://dev.to/martinkordas/how-to-properly-store-and-print-plaintext-strings-41i3</guid>
      <description>&lt;p&gt;Most of the time, users of web applications fill in &lt;strong&gt;dynamic&lt;/strong&gt; textual data in the form of plaintext. These texts are usually stored in a database and then get printed in different ways. Apart from dynamic user data, applications also use &lt;strong&gt;static&lt;/strong&gt; plaintexts for user interface texts and for static items lists. (Static plaintexts could be stored in a database or directly in program data.)&lt;/p&gt;

&lt;p&gt;I decided to share some common tips on how to deal with these plain strings appropriately. For brevity, the article only lists &lt;em&gt;what&lt;/em&gt; should be done with plaintext strings, it does not focus on &lt;em&gt;how&lt;/em&gt; to implement it. In most programming languages, an existing library function could be found to accomplish each of described tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Storing plaintext
&lt;/h2&gt;

&lt;p&gt;Before storing a string received as an user input, you should perform these operations.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Normalize whitespace&lt;/strong&gt;: Normalization provides uniform format for your strings and strip unnecessary or unintended characters. You will probably implement this feature using regular expressions.

&lt;ol&gt;
&lt;li&gt;Strip any whitespace from beginning and end of the string.&lt;/li&gt;
&lt;li&gt;Convert whitespace characters other than space character (e. g. tabulator) into a space character (do not convert line break characters).&lt;/li&gt;
&lt;li&gt;Merge any adjacent whitespace characters into a single space character.&lt;/li&gt;
&lt;li&gt;Normalize line breaks: line breaks are represented by carriage return (CR) or line feed (LF) character. Replace CR or CRLF sequence with LF character (Unix convention) or CRLF sequence (Windows convention).&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strip non-printable characters&lt;/strong&gt;: Today's most common Unicode encoding has also adopted many non-printable characters from the original ASCII character set (e. g. BELL, EOT...). Strip those characters to avoid confusion caused by debugging "invisible" strings. To filter the non-printable characters out, you would usually use a regular expression with specific character value range.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strip unsupported Unicode characters&lt;/strong&gt;: Although UTF-8 encoding is de-facto standard these days, some unusual Unicode characters may not be supported by your systems. For example, MySQL's &lt;code&gt;utf8&lt;/code&gt; charset is capable of storing character of Unicode &lt;em&gt;Basic Multilingual Plane&lt;/em&gt; only. Other characters (e.g. emojis) will not work and you should ideally strip them before processing a storing.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Printing plaintext
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Printing plaintext into plaintext
&lt;/h3&gt;

&lt;p&gt;Web applications usually use HTML as its output format, but occasionally you would use plaintext instead. This includes exporting into text files or sending plaintext e-mails. Printing plaintext into plaintext is naturally easier then printing it into HTML.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Normalize line breaks&lt;/strong&gt;: Thanks to line break normalization before storing, you already have line breaks in an uniform format. You should now however convert it depending on the system where the text will be used. Ideally you would use LF line break style for Unix systems and CRLF sequence for Windows systems. You just have to discover what type the target system is.

&lt;ul&gt;
&lt;li&gt;When sending a file to a client, you could determine client's operating system from the &lt;code&gt;User-Agent&lt;/code&gt; header.&lt;/li&gt;
&lt;li&gt;Alternatively, you could simply always use CRLF sequence, which will work on both Unix and Windows systems most of the time.&lt;/li&gt;
&lt;li&gt;If you are printing into a file stored locally on your server, you should always use line break style specific to your server's operating system.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wrap lines&lt;/strong&gt;: It could be very annoying for user to read lines with excessive length. Check that each line in your text does not exceed suitable limit of characters (e. g. 80 chars) and insert a line break where needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Convert encoding&lt;/strong&gt;: Although we usually use UTF-8 on the web and in database storage, when doing exports some legacy character sets may be preferred by your clients (e.g. &lt;code&gt;ISO-8859-1&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Printing plaintext into HTML
&lt;/h3&gt;

&lt;p&gt;Although it cannot express any formatting, storing plaintext in the database has several advantages over storing HTML itself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;plaintext is smaller in size&lt;/li&gt;
&lt;li&gt;plaintext can be easily read by database admin or by developer when debugging an app&lt;/li&gt;
&lt;li&gt;plaintext is suitable for querying (searching based on user input including fulltext search)&lt;/li&gt;
&lt;li&gt;plaintext represents "neutral", generic form of textual data (whereas text stored as HTML can be used only inside HTML document)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you need to print a plaintext string into HTML, you should try to programatically add all formatting features that plaintext was not able to store. I list some of these below. (Only points marked with '!' are necessary for proper and secure printing of texts into HTML, others are optional.)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Convert URLs into &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tags&lt;/strong&gt;: Do this only if the text is supposed to contain URLs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apply formatting expressed in given markup language&lt;/strong&gt;: Simple markup languages like &lt;em&gt;Markdown&lt;/em&gt; make it possible for users to specify formatting directly in the plaintext. Before printing, plaintext is transformed into HTML using a library function.  Your users however need to be trained to use specific markup language.&lt;/li&gt;
&lt;li&gt;(!) &lt;strong&gt;Convert HTML special characters into corresponding entities&lt;/strong&gt;: This is an absolute necessity for security reasons, as it protects your website against &lt;em&gt;HTML injection&lt;/em&gt;. For example, special character &lt;code&gt;&amp;lt;&lt;/code&gt; would be encoded as entity &lt;code&gt;&amp;amp;gt;&lt;/code&gt; and special character &lt;code&gt;"&lt;/code&gt; as entity &lt;code&gt;&amp;amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Convert all applicable HTML characters into corresponding HTML entities&lt;/strong&gt;: This makes some unusual Unicode characters easier to identify in the source code. For example, © character would be encoded as entity &lt;code&gt;&amp;amp;copy;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Transform characters based on your language's grammar rules&lt;/strong&gt;: Users of your application typically only use basic characters when filling in input fields and do not care much about typography. Hence, your program should intelligently deduce transformations needed for the text to be typographically and grammatically correct. Typically you would replace a character located at appropriate position with an HTML entity.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;amp;nbsp;&lt;/code&gt;: Put non-breaking space instead of simple space wherever a line break is inappropriate. In English for example, you would put non breaking space between number and unit indication ( e. g. &lt;em&gt;10 kg&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;amp;ndash;&lt;/code&gt; or &lt;code&gt;&amp;amp;mdash;&lt;/code&gt;: Basic dash character (-) should be replaced with wider dash characters in many cases. In English for example, you would put ndash character (–) between numerical ranges (e. g. &lt;em&gt;1939–1945&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;amp;hellip;&lt;/code&gt;: &lt;em&gt;Horizontal ellipsis&lt;/em&gt; character (…) should replace three dots at the end of a sentence.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;amp;bdquo;&lt;/code&gt; and  &lt;code&gt;&amp;amp;ldquo;&lt;/code&gt;: Users usually use basic double quote character (") when filling forms. Some languages may however require different stylization for opening and closing quotes (for example „ for opening and “ for closing quotes).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;(!) &lt;strong&gt;Convert line break characters to &lt;code&gt;&amp;lt;br /&amp;gt;&lt;/code&gt; tags&lt;/strong&gt;: Otherwise you will see no actual line breaks on the website.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Wrap lines&lt;/strong&gt;: See above section &lt;em&gt;Printing as plaintext&lt;/em&gt;. Wrapping long HTML lines becomes useful when you read raw HTML source code as a developer, but does not have any impact on user experience.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You should ideally incorporate several of these operations into one function call which you will use as a standard way for printing plaintext into HTML.&lt;/p&gt;

&lt;p&gt;As an alternative approach, you could store plaintext and HTML version of the text simultaneously. This solution saves you from dynamically transforming plaintext every time you need to print it into HTML, but reduces maintainability and increases storage needs.&lt;/p&gt;

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

&lt;p&gt;I consider the above mentioned thoughts to be a structured summary on how to deal with plaintext as a programmer. It is not easy for a beginner to think through all possible eventualities, so I hope this could be helpful.&lt;/p&gt;

&lt;p&gt;If anything is not clear, please write to comments. I can also provide example implementation of some of the described string handling operations.&lt;/p&gt;

</description>
      <category>html</category>
      <category>database</category>
      <category>security</category>
      <category>programming</category>
    </item>
    <item>
      <title>Practical use of callback functions in PHP</title>
      <dc:creator>Martin Kordas</dc:creator>
      <pubDate>Tue, 02 Mar 2021 15:21:38 +0000</pubDate>
      <link>https://dev.to/martinkordas/practical-use-of-callback-functions-in-php-2fcm</link>
      <guid>https://dev.to/martinkordas/practical-use-of-callback-functions-in-php-2fcm</guid>
      <description>&lt;p&gt;Ability to use function callbacks comes very handy in many everyday programming situations. With anonymous functions it is possible to inject your own code into another function's execution, which greatly improves code reuse.&lt;/p&gt;

&lt;p&gt;These are some simple, but highly practical examples of using callbacks for various programming tasks. In each example, we are going to define a helper function that accepts another callback function as an argument and does some processing with it. The helper function can then be reused by calling it repeatedly with custom callback arguments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example1: Time measurement
&lt;/h2&gt;

&lt;p&gt;You have probably already used &lt;code&gt;microtime()&lt;/code&gt; function for benchmarking your program. Now you can define &lt;code&gt;runWithTimer()&lt;/code&gt; helper function, which performs &lt;code&gt;microtime()&lt;/code&gt; calls and time subtractions automatically for you. Code intended for time measurement is passed in a callback parameter &lt;code&gt;$cb&lt;/code&gt; and called from inside of the helper function.&lt;/p&gt;

&lt;h3&gt;
  
  
  Helper function
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;runWithTimer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;callable&lt;/span&gt; &lt;span class="nv"&gt;$cb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$seconds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;$t0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;microtime&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="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nv"&gt;$res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$cb&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;$res&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="nv"&gt;$t1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;microtime&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="nv"&gt;$seconds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$t1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;$t0&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 helper function uses &lt;code&gt;&amp;amp;$seconds&lt;/code&gt; parameter passed by reference to store the resulting number of seconds. Helper function itself returns the return value of the callback function &lt;code&gt;$cb&lt;/code&gt;. It could also be implemented the other way round (helper function returning number of seconds and storing callback function return value in an parameter passed by reference).&lt;/p&gt;

&lt;h3&gt;
  
  
  Usage
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$seconds&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="nv"&gt;$res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;runWithTimer&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="nb"&gt;sleep&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="k"&gt;return&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="nv"&gt;$seconds&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;var_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$seconds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Outputs: float(3.022805929184) bool(true)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Number of seconds the callback function was executing was stored into &lt;code&gt;$seconds&lt;/code&gt; variable. Callback function itself returned &lt;code&gt;TRUE&lt;/code&gt;, which was stored into the &lt;code&gt;$res&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;Note that doing the final time subtraction in &lt;code&gt;finally&lt;/code&gt; block ensures that we get the resulting number of seconds even if the callback function throws an exception.&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;$seconds&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="nv"&gt;$res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;runWithTimer&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="nb"&gt;sleep&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="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="p"&gt;},&lt;/span&gt; &lt;span class="nv"&gt;$seconds&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="nc"&gt;Throwable&lt;/span&gt; &lt;span class="nv"&gt;$ex&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;var_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$seconds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Outputs: float(3.0143301486969) NULL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Example 2: Output buffering
&lt;/h2&gt;

&lt;p&gt;Some of your existing functions may be echoing output instead of returning it as a string. Ideally, you should rewrite those functions to return strings, but as a fast workaround, you can use &lt;a href="https://www.php.net/manual/en/book.outcontrol.php"&gt;output buffering&lt;/a&gt;. &lt;code&gt;runWithOutputBuffer()&lt;/code&gt; helper function encapsulates necessary output buffering calls for you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Helper function
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;runWithOutputBuffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;ob_start&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;$res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$callback&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;$res&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="nv"&gt;$output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;ob_get_contents&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nb"&gt;ob_end_clean&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;h3&gt;
  
  
  Usage
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;runWithOutputBuffer&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;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hello world!"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&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="nv"&gt;$output&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;var_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Outputs: string(12) "Hello world!" bool(true)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, output of callback function was stored as string into &lt;code&gt;$output&lt;/code&gt; variable. Callback function itself returned &lt;code&gt;TRUE&lt;/code&gt;, which was stored into the &lt;code&gt;$res&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;You could also use string-based callback to easily store output of existing echoing 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="nv"&gt;$output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;runWithOutputBuffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"phpinfo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;var_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Example 3: Database transactions
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;runInTransaction()&lt;/code&gt; function stores repetitive code for committing and rolling back database transactions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Helper function
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;runInTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;mysqli&lt;/span&gt; &lt;span class="nv"&gt;$mysqli&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;callable&lt;/span&gt; &lt;span class="nv"&gt;$cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;$mysqli&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;begin_transaction&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;$res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$cb&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nv"&gt;$mysqli&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;commit&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;$res&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="nc"&gt;Throwable&lt;/span&gt; &lt;span class="nv"&gt;$ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$mysqli&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;rollback&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nv"&gt;$ex&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 helper function executes callback &lt;code&gt;$cb&lt;/code&gt; and invokes transaction rollback if the callback throws an exception. Otherwise, it commits the transaction. (Callback &lt;code&gt;$cb&lt;/code&gt; should contain  database data manipulation logic, otherwise it does not make sense to pass it to the &lt;code&gt;runInTransaction()&lt;/code&gt; function.)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;NOTE: In a real project code you would probably implement the helper function as a method of your database connection provider class, so that the &lt;code&gt;$mysqli&lt;/code&gt; object could be stored in a class variable instead of being repeatedly passed through function parameter.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Usage
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;$persons&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="s2"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"name"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"id"&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="s2"&gt;"name"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Monica"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="nv"&gt;$countInserted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;runInTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$mysqli&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="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$persons&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$count&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="nv"&gt;$res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;insertIntoTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"persons1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$persons&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;$res&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="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="k"&gt;else&lt;/span&gt; &lt;span class="nv"&gt;$count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nv"&gt;$res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nv"&gt;$res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;insertIntoTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"persons2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$persons&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;$res&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="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="k"&gt;else&lt;/span&gt; &lt;span class="nv"&gt;$count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nv"&gt;$res&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;$count&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="s2"&gt;"Transaction commited (&lt;/span&gt;&lt;span class="nv"&gt;$countInserted&lt;/span&gt;&lt;span class="s2"&gt; rows inserted)."&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="nc"&gt;Throwable&lt;/span&gt; &lt;span class="nv"&gt;$ex&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="s2"&gt;"Transaction rolled back."&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;In this example, callback represented by anonymous function inserts data into two different database tables. Database manipulation logic is black-boxed in the &lt;code&gt;insertIntoTable()&lt;/code&gt; function. When a database error is signaled by a &lt;code&gt;FALSE&lt;/code&gt; return value, callback function throws an exception, and thus causes transaction rollback. Otherwise, it returns number of inserted rows, which is finally stored in &lt;code&gt;$coutInserted&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;Since &lt;code&gt;$persons&lt;/code&gt; data intended for database insertion were defined outside the scope of the anonymous function, we have applied &lt;code&gt;use&lt;/code&gt; construct in anonymous function definition to bring &lt;code&gt;$perons&lt;/code&gt; variable into the inner scope (&lt;code&gt;function () use ($persons)&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;NOTE: You could use similar helper functions even for other database-related tasks, like executing callback functions against certain default database (you would probably use &lt;code&gt;$mysqli-&amp;gt;select_db(...)&lt;/code&gt; in the helper function code).&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Example 4: Caching
&lt;/h2&gt;

&lt;p&gt;Our final example deals with caching of function return values. Usually you would want to cache resource-consuming calculations, database querying functions or other I/O related calls.&lt;/p&gt;

&lt;p&gt;Similar to previously mentioned helper functions, &lt;code&gt;createCache()&lt;/code&gt; accepts callback function in &lt;code&gt;$cb&lt;/code&gt; parameter. This callback function represents a computation for which we want to cache return values. Helper function finally returns a completely new anonymous function, which can then be used by outer code as a caching function.&lt;/p&gt;

&lt;h3&gt;
  
  
  Helper function
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;createCache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;callable&lt;/span&gt; &lt;span class="nv"&gt;$cb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nv"&gt;$multiArgs&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="nv"&gt;$cache&lt;/span&gt; &lt;span class="o"&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="nv"&gt;$multiArgs&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="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$argument&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$cache&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$cb&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="nb"&gt;array_key_exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$argument&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$cache&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;$cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$argument&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="nv"&gt;$cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$argument&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$argument&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;$cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$argument&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;span class="k"&gt;else&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;function&lt;/span&gt; &lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nv"&gt;$args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$cache&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;$valFound&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="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$cache&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="k"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$args1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$val1&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;$args1&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nv"&gt;$args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nv"&gt;$val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$val1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nv"&gt;$valFound&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;break&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="nv"&gt;$valFound&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;$val&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="nv"&gt;$val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nv"&gt;$args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$cache&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="nv"&gt;$args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$val&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;$val&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;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Helper function first creates &lt;code&gt;$cache&lt;/code&gt; array, which will serve as a storage for cached return values. Then it returns an anonymous function which executes a given callback &lt;code&gt;$cb&lt;/code&gt; and caches its return value, but only if it does not find its return value already stored in the cache. Returned anonymous function could have been created in two branches, which is only a performance tweak - return values of callback functions accepting only one argument can be cached more efficiently, which is what the first branch is for.&lt;/p&gt;

&lt;h3&gt;
  
  
  Usage
&lt;/h3&gt;

&lt;p&gt;We will define &lt;code&gt;getPerson()&lt;/code&gt; function querying person's data from the database and then we create caching function &lt;code&gt;$getPersonCached()&lt;/code&gt; from 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="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getPerson&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$nameOnly&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="s2"&gt;"called widh id &lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;br /&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;$person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;selectFromTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"persons"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$id&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;$nameOnly&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nv"&gt;$person&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$person&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;$getPersonCached&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createCache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"getPerson"&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="nv"&gt;$person1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$getPersonCached&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$person2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$getPersonCached&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"2"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$person1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$getPersonCached&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Outputs:&lt;/span&gt;
&lt;span class="c1"&gt;// called with id 1&lt;/span&gt;
&lt;span class="c1"&gt;// called with id 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you see, repeated call to &lt;code&gt;$getPersonCached()&lt;/code&gt; with argument &lt;code&gt;"1"&lt;/code&gt; hasn't invoked &lt;code&gt;getPerson()&lt;/code&gt; function, because the return value has been obtained from the cache.&lt;/p&gt;

&lt;p&gt;If you wanted to make calls to &lt;code&gt;getPerson()&lt;/code&gt; with the optional parameter &lt;code&gt;$nameOnly&lt;/code&gt; changing, you would have to call &lt;code&gt;createCache()&lt;/code&gt; with parameter &lt;code&gt;$multiArgs&lt;/code&gt; set to &lt;code&gt;TRUE&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="nv"&gt;$getPersonCache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createCache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"getPerson"&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="nv"&gt;$person1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$getPersonCache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$personName1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$getPersonCache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"1"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;NOTE: We have used string-based callback &lt;code&gt;"getPerson"&lt;/code&gt; as an argument for &lt;code&gt;createCache()&lt;/code&gt; function in this examples, but you could naturally use anonymous function callbacks as well.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;I hope this examples helped you to understand how to build better code. They also serve as an introduction to functional programming in PHP.&lt;/p&gt;

&lt;p&gt;For advanced techniques, see following sections of PHP Manual:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.php.net/manual/en/language.types.callable.php"&gt;Callbacks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.php.net/manual/en/functions.anonymous.php"&gt;Anonymous functions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.php.net/manual/en/functions.arrow.php"&gt;Arrow functions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.php.net/manual/en/language.generators.overview.php"&gt;Generators&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Image credit: &lt;a href="https://commons.wikimedia.org/wiki/File:Php_elephant_logo.svg"&gt;https://commons.wikimedia.org/wiki/File:Php_elephant_logo.svg&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>functional</category>
    </item>
  </channel>
</rss>
