<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Jorge Castro on Medium]]></title>
        <description><![CDATA[Stories by Jorge Castro on Medium]]></description>
        <link>https://medium.com/@jorgeccastro?source=rss-df3d6238cc23------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*rxkPuWgpW6IR-DWcE0EI3A.jpeg</url>
            <title>Stories by Jorge Castro on Medium</title>
            <link>https://medium.com/@jorgeccastro?source=rss-df3d6238cc23------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 13:39:39 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@jorgeccastro/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[AI and another new paradigm]]></title>
            <link>https://medium.com/cook-php/ai-and-another-new-paradigm-2163a7d1b67b?source=rss-df3d6238cc23------2</link>
            <guid isPermaLink="false">https://medium.com/p/2163a7d1b67b</guid>
            <category><![CDATA[ai]]></category>
            <dc:creator><![CDATA[Jorge Castro]]></dc:creator>
            <pubDate>Sun, 08 Mar 2026 20:46:48 GMT</pubDate>
            <atom:updated>2026-03-08T20:46:48.862Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*EPNQK1B4iiLeZI6va0FiLg.png" /></figure><p>Right now, I am working on a project. It is not completely using AI, but I am doing lots of magic stuff for coding it, but for any practical purpose, lets asume it is programmed AI.</p><p>I have a typical website to CRUD some database (in React, but the technology doesn’t matter here much)</p><p>3 pages that load a form component, the component is “smart” to display itself differently if it is called by the page insert, update, or delete.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/641/1*Y8_HZeE0iuwsi7pFu1GKvQ.png" /></figure><p>Example:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*jLWUHwoUmtmD2jXl.png" /></figure><p>Reusing of the form component has the following perks:</p><ul><li>One code fits all</li><li>Less code to write</li><li>Reusability</li></ul><p>However, it also limits the <strong>flexibility</strong>. For example, if we want the form for the “page insert” to be different from the form used for the “page update”.</p><p>With AI, those points are not as important because it only means a few extra files and a minute or less of token.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/602/1*zFy-TmhTebJxV6wM2hHrxw.png" /></figure><p>With AI, it&#39;s time to rethink how the older paradigms are worth using, or if we need to rethink them.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/218/0*sW-6jaDMzy-tYIgI.gif" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2163a7d1b67b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/cook-php/ai-and-another-new-paradigm-2163a7d1b67b">AI and another new paradigm</a> was originally published in <a href="https://medium.com/cook-php">Cook php</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Running several processes in PHP]]></title>
            <link>https://medium.com/cook-php/running-several-processes-in-php-badb9e5a5c77?source=rss-df3d6238cc23------2</link>
            <guid isPermaLink="false">https://medium.com/p/badb9e5a5c77</guid>
            <dc:creator><![CDATA[Jorge Castro]]></dc:creator>
            <pubDate>Thu, 02 Jan 2025 13:22:17 GMT</pubDate>
            <atom:updated>2025-01-02T13:25:44.496Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*niDfxHr2N8Xyhwhz" /></figure><h3>Problem</h3><p>I had to analyze and read 14739 folders using PHP, which took over half an hour and I reduced the time to 96 seconds.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/591/0*lr9DLhEDh82Id2y4" /></figure><p>While PHP has some async functionalities, they don’t work in Windows. However, some solutions are still available, such as using CURL calls, exec calls, and COM calls, but, these are based on calling the functionality without getting an answer. What progress does it have? What if the operation failed?</p><p>So, one solution is to use JavaScript and PHP in tandem. Why?</p><ul><li>JavaScript could coordinate a visual interface and the async calls.</li><li>While PHP does the job.</li></ul><p>Then I created this simple library:</p><p><a href="https://github.com/EFTEC/MultiOne">EFTEC/MultiOne: MultiOne is a library to execute concurrent tasks programmed in PHP using JavaScript</a></p><h3>How does it work?</h3><p>It works in 3 stages:</p><ul><li>Starting the jobs and creating the payload for every worker. A worker is the process that does its job.</li><li>Every worker does his job</li><li>And when every worker ends, you can do a final operation.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/410/0*MZ_7ssxfq1fMLRf1" /></figure><p>The code:</p><p>First, we create an instance of the class</p><pre>use Eftec\MultiOne\MultiOne;<br>$work=MultiOne::Factory(<br>    1000, // miliseconds<br>    basename(__FILE__), // the file to call (itself)<br>    4 // number of workers<br>);</pre><p>And we want to call the next 3 functions</p><p>Create the initial works (4 workers, 4 jobs). It could be any value and not just arrays.</p><p>In this case, every worker will be assigned an array or values.</p><pre>static function($numWorkers) {<br>        $work=[<br>            [&quot;apple&quot;,&quot;banana&quot;,&quot;pear&quot;,&quot;orange&quot;,&quot;lemon&quot;],<br>            [&quot;alpha&quot;,&quot;beta&quot;,&quot;gamma&quot;,&quot;delta&quot;],<br>            [&quot;tango&quot;,&quot;charlie&quot;,&quot;foxtrot&quot;],<br>            [1,2,3,4,5,6,7,8,9,10,11,12],<br>        ];<br>        return $work; // we give every worker a work<br>    }</pre><p>Second, we do the work. In this case, we pop an element at the end of the array and we display it. If the array is empty, then we send an “end” command (we stop the worker)</p><pre>static function($idWorker, $payload) {<br>        usleep(500);<br>        $current=array_pop($payload); // apple, banana, etc.<br>        if($current===null) {<br>            return MultiOne::msgAnswer(&#39;end&#39;,$payload,$current.&#39; work done&#39;);<br>        }<br>        return MultiOne::msgAnswer(&#39;run&#39;,$payload,$current);<br>    }</pre><p>And third, when every worker has stopped, we could do a final operation. In this case, we are only returning a simple message.</p><pre>static function($payloads) {<br>    return &#39;work done&#39;;<br>}</pre><p>We add those 3 functions as follows</p><pre>$work-&gt;setMethods(<br>    static function($numWorkers) {<br>        $work=[<br>            [&quot;apple&quot;,&quot;banana&quot;,&quot;pear&quot;,&quot;orange&quot;,&quot;lemon&quot;],<br>            [&quot;alpha&quot;,&quot;beta&quot;,&quot;gamma&quot;,&quot;delta&quot;],<br>            [&quot;tango&quot;,&quot;charlie&quot;,&quot;foxtrot&quot;],<br>            [1,2,3,4,5,6,7,8,9,10,11,12],<br>        ];<br>        return $work; // we give every worker a work<br>    },<br>    static function($idWorker, $payload) {<br>        usleep(500);<br>        $current=array_pop($payload);<br>        if($current===null) {<br>            return MultiOne::msgAnswer(&#39;end&#39;,$payload,$current.&#39; work done&#39;);<br>        }<br>        return MultiOne::msgAnswer(&#39;run&#39;,$payload,$current);<br>    },<br>    static function($payloads) {<br>        return &#39;work done&#39;;<br>    }<br>);</pre><p>Finally, we execute the class</p><pre>$work-&gt;runAuto();</pre><p>Our entire code will look as follows</p><pre>$work=MultiOne::Factory(<br>    1000, // miliseconds<br>    basename(__FILE__), // the file to call (itself)<br>    4 // number of workers<br>);<br>$work-&gt;setMethods(<br>    static function($numWorkers) {<br>        $work=[<br>            [&quot;apple&quot;,&quot;banana&quot;,&quot;pear&quot;,&quot;orange&quot;,&quot;lemon&quot;],<br>            [&quot;alpha&quot;,&quot;beta&quot;,&quot;gamma&quot;,&quot;delta&quot;],<br>            [&quot;tango&quot;,&quot;charlie&quot;,&quot;foxtrot&quot;],<br>            [1,2,3,4,5,6,7,8,9,10,11,12],<br>        ];<br>        return $work; // we give every worker a work<br>    },<br>    static function($idWorker, $payload) {<br>        usleep(500);<br>        $current=array_pop($payload);<br>        if($current===null) {<br>            return MultiOne::msgAnswer(&#39;end&#39;,$payload,$current.&#39; work done&#39;);<br>        }<br>        return MultiOne::msgAnswer(&#39;run&#39;,$payload,$current);<br>    },<br>    static function($payloads) {<br>        return &#39;work done&#39;;<br>    }<br>);<br>$work-&gt;runAuto();</pre><p>If we call this PHP file, it will show the next values</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/511/0*irinOXyILsRBWpqQ" /></figure><p>It’s simple and it works.</p><p>A new version</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/477/0*A57ClhxSrqSgmoBv" /></figure><p>Code:</p><pre>$work=MultiOne::Factory(<br>    1000, // miliseconds<br>    basename(__FILE__), // the file to call (itself)<br>    4 // number of workers<br>);<br>$work-&gt;setMethods(<br>    static function($numWorkers) {<br>        $work=[<br>            [[&quot;apple&quot;,&quot;banana&quot;,&quot;pear&quot;,&quot;orange&quot;,&quot;lemon&quot;],5],<br>            [[&quot;alpha&quot;,&quot;beta&quot;,&quot;gamma&quot;,&quot;delta&quot;],4],<br>            [[&quot;tango&quot;,&quot;charlie&quot;,&quot;foxtrot&quot;],3],<br>            [[1,2,3,4,5,6,7,8,9,10,11,12],12],<br>        ];<br>        return $work; // we give every worker a work<br>    },<br>    static function($idWorker, $payload) {<br>        usleep(500);<br>        $txt=str_repeat(&#39;📦&#39;,count($payload[0])).str_repeat(&#39;✅&#39;,$payload[1]-count($payload[0]));<br>        $current=array_pop($payload[0]);<br>        if($current===null) {<br>            return MultiOne::msgAnswer(&#39;end&#39;,$payload,$txt);<br>        }<br>        return MultiOne::msgAnswer(&#39;run&#39;,$payload,$txt);<br>    },<br>    static function($payloads) {<br>        return &#39;work done&#39;;<br>    }<br>);<br>$work-&gt;runAuto();</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=badb9e5a5c77" width="1" height="1" alt=""><hr><p><a href="https://medium.com/cook-php/running-several-processes-in-php-badb9e5a5c77">Running several processes in PHP</a> was originally published in <a href="https://medium.com/cook-php">Cook php</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Using ORM in PHP without a framework.]]></title>
            <link>https://medium.com/cook-php/using-orm-in-php-without-a-framework-d01040a85ade?source=rss-df3d6238cc23------2</link>
            <guid isPermaLink="false">https://medium.com/p/d01040a85ade</guid>
            <category><![CDATA[php]]></category>
            <category><![CDATA[orm]]></category>
            <category><![CDATA[pdo]]></category>
            <dc:creator><![CDATA[Jorge Castro]]></dc:creator>
            <pubDate>Sat, 11 Mar 2023 22:59:08 GMT</pubDate>
            <atom:updated>2023-03-11T22:59:08.798Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*oiobiAEaD-M23I_Y" /></figure><h3>What is an ORM?</h3><p>An ORM is an abstraction of the information of the database. For example, let’s say we have a list of cities and we want to list it.</p><p>It is the PHP PDO version:</p><pre>$stmt = $pdo-&gt;prepare(&quot;SELECT * FROM cities&quot;);<br>$stmt-&gt;execute();<br>$result = $stmt-&gt;get_result();<br>$cities=[];<br>while($row = $result-&gt;fetch_assoc()) {<br>  $cities[]=$row; <br>}<br>$stmt-&gt;close();</pre><p>While this code could work but it is prone to mistakes and it could be tedious in the long term. What if we could simplify it and turn more focused into a PHP model? That is the concept of ORM.</p><p>And it is the ORM version of it.</p><pre>$cities=CitiesRepo::toList();</pre><p>The ORM version is simple but there is more about ORM.</p><p>In general, ORM allows abstracting access to the database simplifying it.</p><blockquote>ORM is not a solution fits all. I will explain it later.</blockquote><p>Sometimes we don’t want to add a whole framework to do this job, this example is about that.</p><h3>Getting started</h3><p>For this example, you will need:</p><ul><li>PHP 7.1 or higher.</li><li>PHP must have the PDO and PDOMYSQL extensions installed.</li><li>Composer</li><li>Mysql with the example tables</li><li>For this example, I will use the next database: <a href="https://github.com/escuelainformatica/Sakila-Database-2021">Sakila-Database-2021</a></li><li>1) Create a new project using composer and add our library. (open a terminal, bash, PowerShell, cmd, etc.)</li></ul><pre>composer init  # and fill the information of your project.<br>composer require eftec/pdoonerepo</pre><ul><li>If the composer fails, then remember to install it and add it to the path.</li><li>2) Once it is done and the libraries are downloaded, then run the next command</li></ul><pre>./vendor/pdooneorm</pre><p>It will show the next screen</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1007/0*t6I4nWjiBT111dHJ" /></figure><p>And now, you are in interactive mode.</p><p>In interactive mode you can:</p><ul><li>select your own option</li><li>if you write “?” then it shows a simple help, that explains what command does what.</li><li>If you write “??” then it shows technical help</li><li>If you press the key tab, then you can autocomplete the options, so you won’t need to write all the options.</li><li>If you press arrow-up or arrow-down then you can navigate in the history (if any).</li></ul><p>The first option is it shows [connect] [pending] It is because we aren’t connected to the database.</p><p>Write “connect” to enter the connect menu so we could create a new connection (remember that you can use autocomplete, i.e. if you write comple&lt;table&gt; then it will autocomplete the rest)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/727/0*L6KBX6sOC9GeWoKO" /></figure><p>Then enter the option “configure”.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/805/0*Rd0nKG7KZ9bCmdVQ" /></figure><p>And configure your database. If you fail, then you can try it again.</p><ul><li>the type of database: “MySQL”</li><li>the server: 127.0.0.1 in my case.</li><li>The user: root</li><li>The password: abc.123 ← that is my password, so please keep it secret (wink wink).</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/480/0*a1qXJyji55_GnNfx.gif" /></figure><ul><li>And the schema: “sakila” (or the schema that you want to use)</li></ul><p>Once it is done, it will show:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/681/0*Zn4yifeGaQc2c-XU" /></figure><p>the [ok] says that we are [ok] with this step. For example, you can save without configuration but it does not make any sense.</p><p>And about saving, enter the option “save” and save your configuration because you don’t want to re-enter the entire configuration every time.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/926/0*yYyFPQ4plfhFDl28" /></figure><p>It will save the next file: config.config.php</p><pre>&lt;?php http_response_code(404); die(1); // eftec/CliOne(1.24) configuration file (date gen: 2023-03-11 17:40)?&gt;<br>{<br>    &quot;databaseType&quot;: &quot;mysql&quot;,<br>    &quot;server&quot;: &quot;127.0.0.1&quot;,<br>    &quot;user&quot;: &quot;root&quot;,<br>    &quot;pwd&quot;: &quot;abc.123&quot;,<br>    &quot;database&quot;: &quot;sakila&quot;<br>}</pre><p>You can reload the configuration using the option “load” or call as a flag.</p><p>But what this file means?</p><ul><li>It is a PHP file that contains a JSON inside.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/581/0*sxPXyQRkPI-U6tRp.gif" /></figure><p>Lets me explain about security. Let’s say we write this file as config.json and we commit the mistake to avoid locking it, so everybody could read this configuration as mydomain.dom/config.json<br>Now, since it is a PHP file, then even if it is available directly, then mydomain.dom/config.config.php will return a 404 empty page. So, this file is already safe from prying eyes. How course, it keeps the password in plain sight, so it is not safe if you are exposing your configuration file to others.</p><p>It is a really common vulnerability.</p><p>About loading the previous configuration, you can load it in interactive mode or you could load it using the command line:</p><pre>pdooneorm --fileconnect config</pre><p>You can also save the file as a PHP file. It is the PHP file version</p><pre>&lt;?php // eftec/CliOne(1.24) PHP configuration file (date gen: 2023-03-11 17:50). DO NOT EDIT THIS FILE <br>/**<br> * it is the configuration of PdoOne<br> */<br>$pdoOneConfig=[<br>    &#39;databaseType&#39; =&gt; &#39;mysql&#39;,<br>    &#39;server&#39; =&gt; &#39;127.0.0.1&#39;,<br>    &#39;user&#39; =&gt; &#39;root&#39;,<br>    &#39;pwd&#39; =&gt; &#39;abc.123&#39;,<br>    &#39;database&#39; =&gt; &#39;sakila&#39;,<br>];</pre><p>It is also a safe file and you can expose it to the world and nobody will see its content. This file could be used later to code (or you could simply copy and paste its content).</p><h3>Creating the repository classes</h3><p>Once we are connected, we could use the options available in the menu “repo”.</p><p>It is the repo menu. It has its own configuration but it also requires a connection.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*4EjVQ6S2N1cqeT5N" /></figure><ul><li>Use the “scan” option.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*sigCIg8cKz7NIuSp" /></figure><ul><li>1) it will show that it is reading the structure. It is an important part. The library scans for tables and creates a catalog about what tables exist, what structure, relations, etc.</li><li>2) Once it is done, then it will show [ok]</li><li>For every new change, then you must run this command.</li></ul><p>And now, let’s determine the folders. Use the “folder” option.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*-ifPayTVRPKmhbHY" /></figure><ul><li>Select the relative directory. My example is “repo”.</li><li>Select the postfix of the class. If the class is called City, then the repository class will be called CityRepo.</li><li>The current path (for my example) is</li><li>D:\www\currentproject\PdoOneORM\examples\example2/repo</li><li>For the next step, we will need to configure Composer.</li><li>It is part of my composer.json</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/496/0*nyoKPFFTTrBQ8CWD" /></figure><ul><li>I will try to find a namespace that fits my route. In my case, it is my namespace. i.e:</li><li>folder: <strong>D:\www\currentproject\PdoOneORM\examples\</strong></li><li>namespace:<strong> eftec\examples</strong></li><li>Since my folder is <strong>D:\www\currentproject\PdoOneORM\examples\example2/repo</strong></li><li>then the namespace must be<br><strong>eftec\examples\example2\repo</strong></li><li>If you do have not a path in composer, then save your configuration, close the program, then edit composer and re-open the program again.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*X22umDEvQbp0QOgT" /></figure><p>So, we have configured:</p><ul><li>✅ connection</li><li>✅ folder</li><li>✅scan.</li></ul><p>So we could create the code. Use the option “create”</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*jFFZXr4V3jryTHVH" /></figure><p>It will populate the repo folder with many files</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*fLdtrHDqQkfdUCdj" /></figure><p>Mainly there are 3 kinds of files.</p><ul><li>Abstract classes. It will contain the definition of the table, indexes, relations, etc. You should not edit those files because if you “scan” again, it will rebuild this file.</li><li>Repo classes, is the file that you can edit.</li><li>Base class. There is a simple class (in this case called Sakila) that is used for all other classes. It has relations between classes.</li></ul><blockquote>Don’t forget to save your configuration.</blockquote><h3>Using the repo classes.</h3><p>In the same folder, write the next code: example1.php</p><pre>&lt;?php<br>include __DIR__.&quot;/../../vendor/autoload.php&quot;; // edit the path for the correct one.<br>$cities=eftec\examples\example2\repo\CityRepo::toList();<br>var_dump($cities);</pre><p>If you run this example, then it will fail because you are not connected to the database.</p><p>Do the next modification</p><pre>&lt;?php<br>use eftec\PdoOneORM;<br>use eftec\examples\example2\repo\CityRepo;<br>include __DIR__.&quot;/../../vendor/autoload.php&quot;; // edit the path for the correct one.<br>$conn= PdoOneORM::factoryFromArray([<br>    &#39;databaseType&#39; =&gt; &#39;mysql&#39;,<br>    &#39;server&#39; =&gt; &#39;127.0.0.1&#39;,<br>    &#39;user&#39; =&gt; &#39;root&#39;,<br>    &#39;pwd&#39; =&gt; &#39;abc.123&#39;,<br>    &#39;database&#39; =&gt; &#39;sakila&#39;,<br>]); // you can include the PHP file generated previously or copy and paste its configuration.<br>$conn-&gt;open(); // opens the database connection. $conn is a singleton, so you don&#39;t need to open it every time you want to use.<br>$conn-&gt;logLevel=3; // it is optional,<br>$cities=CityRepo::toList(); // $conn is injected automatically inside every &quot;Repo&quot; class.<br>var_dump($cities);</pre><p>It will show:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/607/0*fqWjmC-81B-xs00x" /></figure><p>But we could do even more. In this case, the table “city” is related to the table “country”.</p><p>Edit the line where you list the repo as follows:</p><pre>$cities=CityRepo::recursive([&#39;/_country_id&#39;])-&gt;toList();</pre><p>The function recursive will try to load this field. How do you know the name of the field? Every field indicated here starts with “/”. If you look at the code of CityRepo, it will show every field:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*su8_S8zgougI8CTL" /></figure><p>It says that “_<em>country_</em>id” is a many-to-one relational field. Also “__address” is another relational field (one-to-many)</p><p>You can fetch both tables as follow:</p><pre>$cities=CityRepo::recursive([&#39;/_country_id&#39;,&#39;/_address&#39;])-&gt;toList();</pre><h3>ORM or not.</h3><p>ORM could make our life easiest but it could have some hidden costs.</p><ul><li>many-to-one relations are “join” in disguise.</li><li>“one-to-many” relations are multiple queries.</li><li>ORM also loads every row and sometimes the internal queries could be long</li></ul><pre>select address.address_id as `/address_id`,address.address as `/address`,address.address2 as `/address2`,address.district as `/district`,address.city_id as `/city_id`,address.postal_code as `/postal_code`,address.phone as `/phone`,address.last_update as `/last_update` from address where address.`city_id` =&#39;599&#39;</pre><p>If we want performance or we simply want to show a table, then we could use a native query:</p><pre>$cities=CityRepo::query(&#39;select * from city inner join country on city.country_id=country.country_id&#39;);</pre><p>It will return the next fields:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/413/0*tuLt3USphv8k4AZG" /></figure><p>While the result is similar to the ORM but the structure is different.</p><h3>Other examples</h3><pre>// inserting<br>$newCity=[&#39;city&#39; =&gt; &#39;new city&#39;,&#39;country_id&#39; =&gt; 105];<br>CityRepo::insert($newCity);<br>// updating<br>$newCity[&#39;city&#39;]=&#39;name changed&#39;;<br>CityRepo::update($newCity);<br>// deleting<br>CityRepo::delete($newCity);<br>// delete by id<br>CityRepo::deleteById(100);</pre><p>There are more than +100 features available to use but they are the basic ones.</p><h3>Costs</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/512/0*mxXeqKVJjBAOJ2Sx.png" /></figure><p>Why not a framework?</p><ul><li>This library consists of 11 files</li><li>The complete dependency of this library is 28 files.</li><li>The example consists of 37 files.</li></ul><p>So, the whole project example is less than 100 files. It doesn’t all the job as a framework but it is a start.</p><p>In comparison, PHPUnit alone has +500 files and a project in Laravel is over +6000 files.</p><blockquote>The more files, the slow to deploy, it uses more space, and PHP must deal with more files in the memory (OpCache must retain a catalog with every file). Even “Composer autoload” must have a huge file with all the files.</blockquote><p>Also, since it is a simple project, you could even deploy without using Composer, however, you must include the files on your own.</p><p>Plus, you can even use it inside a framework.</p><h3>Why or why not an ORM?</h3><p>Sometimes we want both cases. For example, for the frontend, we could use native operations because they are fast and we don’t need the whole structure of the ORM, and for the backend, we could use the ORM because it is easy to work with it.</p><p>So about ORM, the answer depends, and usually, the solution is both.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d01040a85ade" width="1" height="1" alt=""><hr><p><a href="https://medium.com/cook-php/using-orm-in-php-without-a-framework-d01040a85ade">Using ORM in PHP without a framework.</a> was originally published in <a href="https://medium.com/cook-php">Cook php</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Cloudflare is testing my patience.]]></title>
            <link>https://jorgeccastro.medium.com/cloudflare-is-testing-my-patience-56a85da8199a?source=rss-df3d6238cc23------2</link>
            <guid isPermaLink="false">https://medium.com/p/56a85da8199a</guid>
            <category><![CDATA[cloudflare-wordpress]]></category>
            <category><![CDATA[cloudflare]]></category>
            <dc:creator><![CDATA[Jorge Castro]]></dc:creator>
            <pubDate>Sat, 25 Feb 2023 01:35:22 GMT</pubDate>
            <atom:updated>2023-02-25T01:35:22.257Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*wJRpHjZZwVe2ExBX.jpg" /></figure><p>I there, I use cloudflare for some of my servers. I tried using the cache system but while it works, it also adds more time to the load of the page (TTFB *) so I didn’t worked for me at least in most websites. But, I still use the DNS service which is available to use without cache. So I use mainly for the DNS and only a few pages uses the cache. Nothing wrong here.</p><blockquote>(*) CloudFlare says that the TTFB delay is not a big issue. I think the opposite.</blockquote><p>However, recently I found the next problems:</p><ul><li>Cloudflare affects somehow the content of some pages even when you are not caching it. How, and why? I don’t know but Google Bots shows me some nonexistent links that were generated by CloudFlare.</li><li>And now, somebody is using the IP of Cloudflare to probe one of my server.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VKZePQvfKle913WC_ae86g.png" /></figure><ul><li>The IP is owned by CloudFlare <a href="https://www.cloudflare.com/ips-v4">https://www.cloudflare.com/ips-v4</a></li><li>And my website does not use WordPress in any way and there is no file (or folded) with such name. Also, there is no content or link to that file. I double-checked that.</li></ul><p>So, what is going on with CloudFlare?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/0*rJClktD9pG8pnVQu.jpg" /></figure><p>I don’t think CloudFlare is trying to hack my server and maybe somebody is using CloudFlare as some kind of proxy. But, since I don’t really know what is going on, then that IP of CloudFlare was banned from my system.</p><p>In any case, I think it is time to move out of CloudFlare.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=56a85da8199a" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Short: Why you should create a open source project?]]></title>
            <link>https://jorgeccastro.medium.com/short-why-you-should-create-a-open-source-project-3c27476c14fd?source=rss-df3d6238cc23------2</link>
            <guid isPermaLink="false">https://medium.com/p/3c27476c14fd</guid>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[open-source]]></category>
            <dc:creator><![CDATA[Jorge Castro]]></dc:creator>
            <pubDate>Wed, 22 Feb 2023 11:34:41 GMT</pubDate>
            <atom:updated>2023-02-22T11:34:41.686Z</atom:updated>
            <content:encoded><![CDATA[<p>Why we should spend time creating an open source project?</p><h3>Is it for money?</h3><p>No, most open source projects barely receive any donation. Even top projects could receive less than 100 donors (each one donating around $1-$5 bucks per month). Is it not even enough to pay the time invested.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/0*KzJOxvtAz70aC5qy.jpg" /></figure><h3>Is it for the curriculum?</h3><p>Nope. Interviewers barely care about it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*r5CZhgKSLnjn8cA7.jpg" /></figure><h3>Is it for the fame?</h3><p>Haha, no.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/0*vSc68rMG3dxcDSfC" /></figure><h3>So why?</h3><p><strong>It is for you.</strong></p><p>If you have a private library for a project, then when the project is done, then you most likely will abandon the library. When you create a library for a project, you usually are creating a solution that only fits a single needing.</p><p>While it could sound practical but if you are developing many projects, then sooner or later you found yourself creating a similar library many time.</p><p>Now, if you create an open source project, then you are publishing it and that is the important part. You are exposing a code everybody could look at it and in some cases (rare cases), people could find and solve bugs.</p><p>If it is an open source project, then it is easy to share with your team, and the team could share, edit, etc. and they could follow some <strong>standard and guideline(*)</strong>. And thanks to the modern services (github, bitbucket, etc.) then it is way to easy to share an open source project than a close one.</p><blockquote>(*) How does it work?. commonly in a private project, nobody care to add documentation, explanation, etc. However, it is not the same with a code that everybody could look at it (not always). For example, we used a project where one of the comment said “He bob, check this code” (ps: bob never checked the code). Close source libraries trend to cut a lot of corners, after all, this code is for one usage.</blockquote><p>You could also create a private repository but if you migrate of company, then while you could copy it in a pendrive and bring it to the new company. However, your new team will be less willing to adopt it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/493/0*TocAAkJELKGUN8Bh.gif" /><figcaption>Developer: I don’t want to adopt a close source library created by the new guy of the team</figcaption></figure><p>Also, legally if you work for a company developing code, then the close source code is owned by the company. It is not the same with an open source project. Of course, you don’t want to open source strategic code.</p><h3>i.e.</h3><p>When you share a project with others, then you also sharing a project with the “you” from the future.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3c27476c14fd" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How not to poach a senior developer]]></title>
            <link>https://jorgeccastro.medium.com/how-not-to-poach-a-senior-developer-2b154eb56ed5?source=rss-df3d6238cc23------2</link>
            <guid isPermaLink="false">https://medium.com/p/2b154eb56ed5</guid>
            <category><![CDATA[hiring-strategy]]></category>
            <category><![CDATA[hiring-process]]></category>
            <category><![CDATA[programming]]></category>
            <dc:creator><![CDATA[Jorge Castro]]></dc:creator>
            <pubDate>Mon, 31 Oct 2022 13:59:59 GMT</pubDate>
            <atom:updated>2022-10-31T14:07:25.605Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*z2hZ5B-EcSrF1M70" /><figcaption>We are hiring in the most unpractical way!</figcaption></figure><p>How not to poach a senior developer in easy steps:</p><ul><li>To be unclear with a new proposal of work. Where? conditions? 🚩</li><li>Never mention salary until later in the process. Because the time of a senior developer (that most likely is already working) is worth nothing /s. 🚩</li><li>Start with a “<strong>initially </strong>you will earn… but later you <strong>could </strong>earn”. That is a another red flag. 🚩</li><li>Do some online test where the candidate must remember some programming concepts or write a code by hand. I wonder how many seniors developers don’t know how to use Google. 🚩</li><li>And hire some developer as simple programmer with no decisions in the process. So, you are poaching a senior developer that most likely lead a team, and you want to put instead lower in the “food chain”. 🚩</li><li>And I forget, requirements that obviously were written by somebody that is not a developer (and most likely copy and pasted from the newspaper or magazine). 🚩</li></ul><p>PS: For some odd reasons, Germany is in a frenzy by hiring developers but, apparently Germany is not hiring developers because they need developers but they need CHEAP developers. Under the current market, companies have the next options:</p><ul><li>cheap</li><li>good</li></ul><p>pick one of them.</p><p>Any lower than €70,000 euros per year is a shitty job.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*DUpU87Cy_ampA2Ss" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2b154eb56ed5" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why Flutter rules in a nutshell]]></title>
            <link>https://jorgeccastro.medium.com/why-flutter-rules-in-a-nutshell-3128294f9772?source=rss-df3d6238cc23------2</link>
            <guid isPermaLink="false">https://medium.com/p/3128294f9772</guid>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[flutter-ui]]></category>
            <dc:creator><![CDATA[Jorge Castro]]></dc:creator>
            <pubDate>Sun, 28 Aug 2022 15:22:54 GMT</pubDate>
            <atom:updated>2022-08-29T12:19:29.840Z</atom:updated>
            <content:encoded><![CDATA[<h3>1) Flutter stinks because it uses a different language (Dart) and I don’t want to learn a new language</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*535ImzAAggZfAtCuHePxLQ.jpeg" /></figure><p>Dartis quite similar to C# in several aspects. In fact, it is more like a C# minus all the mumbo jumbo of C#.</p><p>For example, you don’t need “public”, “private”, “protected”, etc. Dart doesn’t have it (it has a prefix “_” for private but you are free to use it or not). In general, in Dart, every field is private, you can use setter and getters but it is not the way of Dart.</p><p>Second, the management of NULL is top notch and it is better than C#</p><p>In C# you could have: <strong>SomeClass instance=null;</strong></p><p>In Dart, you could not have that variable that stores a null, no matter if it is an object or not. So, we will never ever have null pointers unless we explicit allow it. Dart is what we could call, a safe language.</p><p>But in general, if you know C#, then you know Dart.</p><p>In short, you can learn Dartin a weekend. The only “weirdness” is Stream and the constructors.</p><h3>2) I don’t want to learn a new way to write a template</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*fHVf1OrXr2PO-igpVjR7hg.jpeg" /></figure><p>Flutter uses a different approach. It doesn’t use a template language at all. Everything is code. It is a nightmare if you want to use a fancy GUI editor but since practically every GUI editor is horrible (excluding XCode and IOS), then it is not a big deal. JSX, XAML, Blazor etc. are horrible (especially XAML), so you are free from them. Why they are horrible? It is because they are many differences between in what we draw versus in what we finally saw. For example, it is not the same to see an empty list versus a list full of data.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/0*V5qGGFilLihPvC4M.png" /></figure><p>The advantage is the integration between the code and the “template” is seamless, because everything is code. If you learn Dart, you learn “templating Flutter”.</p><p>Plus: Flutter was designed and created thinking in Hot Reload, so it is easy to design a widget and see the changes instantly.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*M9FKRpSoM7Uu-ynv.gif" /></figure><h3>3) I don’t want to deal with fluid components</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*sA8dpfV6-AknAFrBcvlNyQ.jpeg" /></figure><p>Most flutter Widgets don’t scale visually, and the few ones that scale, mostly use the whole space. You must do it on your own. This means, that we don’t deal with “anchors” or some wacky components that automatically screw our design.</p><h3>4) And what about State management.</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*Z2Ogn-UggX_Mi7D5uEcKQg.jpeg" /></figure><p>Every widget in flutter has their own fields but you don’t even need fields inside a widget to keep and draw some values.</p><p>Flutter works mainly with a simple function: setState() and nothing else much (the other is initState())</p><p>Flutter doesn’t work with state directly but with differences in the widgets. If the widget is considered “dirt”, then it draws only the parts that have changed, no matter the states or values. You can even use global variables as “states” or a function. Flutter doesn’t care, it simply works!.</p><h3>5) I don’t want to learn a new framework</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*D3RZnq5qqw3n65792gEhCQ.jpeg" /></figure><p>Flutter consists mainly in two kind of classes.</p><ul><li>Stateless Widgets</li><li>Stateful widgets.</li></ul><p>And nothing more!.</p><p>While Flutter has “states” but they are not the same as other frameworks. The states are just variables (field, global, a function, you name it). So you won’t find a complex flow to manage states such as Redux.</p><p>React Redux flow: (it is just one of many flows of react)</p><figure><img alt="How to implement Redux in React Native apps" src="https://cdn-images-1.medium.com/proxy/1*2--d_JqkSBPUBIe_TsppPA.jpeg" /></figure><p>It is the flow of a Stateful widget (the green step are a simple function).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/936/0*Qe7q4V-3eu_2dkMJ.png" /></figure><p>And Stateless widgets are the same, minus the setState() and didUpdateConfig().</p><h3>Developing for Flutter is the same as to develop a pyramid</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/587/0*TW6nu9QiHSR7rE4V.jpg" /></figure><p>Why? We usually create code inside code, inside code inside code. We could split it creating widgets but finally everything is inside other thing (excluding the main function).</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3128294f9772" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Experience about Command Line Interface (CLI)]]></title>
            <link>https://medium.com/cook-php/experience-about-command-line-interface-cli-287b19a821b?source=rss-df3d6238cc23------2</link>
            <guid isPermaLink="false">https://medium.com/p/287b19a821b</guid>
            <category><![CDATA[cli]]></category>
            <dc:creator><![CDATA[Jorge Castro]]></dc:creator>
            <pubDate>Tue, 15 Feb 2022 22:08:13 GMT</pubDate>
            <atom:updated>2022-02-15T22:10:53.311Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*osGZir5GAEdbSEq-" /></figure><p>I finished writing a library for PHP and I found a lot of details about CLI in general.</p><p><a href="https://github.com/EFTEC/CliOne">GitHub - EFTEC/CliOne</a></p><h4>But first, what is a CLI and why CLI?</h4><p>CLI is a program that works in the line command (shell, cmd, PowerShell). Usually, it is considered GUI-less but some CLI also contains GUI. Here, I will talk about a GUI-less interface</p><p>If you are creating a code for the average end-user (for example somebody non-programmer), then most likely no, it is not the right tool. The average end-user will prefer something more easy to work with it, with a GUI, maybe a website or an application.</p><p>However, if your end-user is a programmer or technician, then it makes a lot of sense to write a CLI instead of building something with a visual interface.</p><h4>Two ways to work with CLI — Argument</h4><p>There are two ways to work with CLI, as an argument or as user input.</p><p>Example:</p><p>program <strong>-argument 1</strong> <strong>-argument 2</strong></p><p>Where you can pass one or multiples arguments to a program.</p><p>Pro:</p><p>✅ You can chain with other scripts</p><p>✅ You can repeat the command many times by copying the execution line. For example, I needed to create 20 virtual machines in Azure and while it is possible to create using the Azure portal (website), it will take a lot of time. Azure allows to run it via a command line, so I write the line to create 1 virtual machine, and I duplicated it 20 times (changing the names of every virtual machine).</p><p>✅ You can even do some extra tricks such as input or output values.</p><p>Cons:</p><p>❌ Security concern, every argument is stored in the history shell, so you don’t want to write a password here.</p><p>❌ You don’t want to use more than 10 arguments. Example:</p><p>program.exe -argument1 hello -argument2 hello -argument3 hello -argument4 hello -argument5 hello -argument6 hello….</p><p><strong>Note: It’s curious but there is not a standard or even good practice to write arguments for a console line program. GNU and POSIX have some kind of standard but it is not completely followed by them, while Microsoft follows different rules. Also, every developer could follow their own rules.</strong></p><p>Example:</p><ul><li><strong>“-argument”</strong> with a simple “-” at the beginner.</li><li><strong>“ — argument”</strong> an argument with a double “-” and the beginner.</li><li><strong>“argument”</strong> without any “-” at the beginning of the operation.</li><li>And some tools allow both, one with a short name, and with a long name. Does it help? Not really, it makes it hard to understand some code.</li></ul><p>Also, some arguments are written with a “=”</p><ul><li><strong>“-argument=value”</strong></li><li><strong>“-argument value”</strong></li></ul><p>And even more. In some programs, arguments are case sensitive, for example</p><ul><li><strong>“-a”</strong></li><li><strong>“-A”</strong></li></ul><p>Both arguments could do something completely different.</p><p>But even when there is not a standard, it is still usable. Mainly because it is aimed at people to know what they are doing. However, some CLI commands are highly dangerous and accident happens.</p><h3>Two ways to work with CLI — User Input</h3><p>There is another way to work: user input or the user enters (manually) the information.</p><blockquote>&gt;program.exe</blockquote><blockquote>what is the value of the first value? <strong>hello ← ✋ user input</strong></blockquote><p>Pro:</p><p>✅ Security concern.</p><p>✅ You can use as many values as you want to.</p><p>✅ The user has more interactivity with the tools, including the chance to select values, mark values, enter more than one value, re-try to enter values, etc.</p><p>Cons:</p><p>❌ You can’t chain with other scripts</p><p>❌ You can’t repeat the command by copying the execution line.</p><p>In any case, you can use both methods to write your CLI program.</p><h3>However, why CLI?</h3><p>There are many advantages to using a CLI:</p><ul><li>It is easy to program. It is easy to create a program with dozen of options by simply adding a few lines of code.</li><li>Some CLI programs are multi-platform by nature, it runs everywhere (Windows, Linux and Mac).</li><li>It doesn’t require a server.</li><li>It uses less bandwidth.</li><li>(as I said), it is possible to add it into another script or chain with other scripts.</li></ul><p>Also, there is another advantage:</p><ul><li><strong>It’s safe (for servers).</strong></li></ul><p>Why?</p><p>Most servers, if not all servers, only allow administrators to access the command line (shell), so the only way to call this program (CLI) is to have access to the server. It is different with a website (for example a backend), where everybody could access it (if it has the access). While a CLI is by default protected by good practices of any good administrator.</p><p>Also, it is possible to restrict and allows permission to only system administrators by using a few commands. Example:</p><blockquote>sudo mycliprogram</blockquote><p>You can leave some script exposed to the world and hackers will not be able to enter the system. Maybe they could get some information (if they could read the script as a file) but nothing more.</p><p>But there is another advantage:</p><ul><li><strong>CLI is more straightforward.</strong></li></ul><p>Why?</p><p>Commonly a GUI could contain many operations and actions in the same screen, such as input text, buttons, combo boxes, etc.</p><p>A CLI is way more straightforward, and usually, the user is aimed to do a specific task in a specific order, for example:</p><ol><li>What is your name? ____</li><li>What is your age? ____</li><li>What is your email? ____</li></ol><p>While it also limits the options that the user could do but it is also one way (or a few ways) to do something.</p><p>It is possible to create a step-by-step (or wizard) using a website, but even when the website could limit the options but the nature of the GUI allows other additionals, such as going back, refreshing, clicking a different link, abandoning the page, etc.</p><p>CLI is also more straightforward to install. Sometimes it simply requires to install a single file and nothing more.</p><h3>Ugly</h3><p>However, CLI mustn’t be specifically ugly. It must not be too fancy but it could contain colours.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/432/0*DAU2gPdl8wJIR7_t.png" /></figure><p>There are some CLI programs that try to mimick the behaviour of the GUI, that even include a mouse, windows, etc.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=287b19a821b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/cook-php/experience-about-command-line-interface-cli-287b19a821b">Experience about Command Line Interface (CLI)</a> was originally published in <a href="https://medium.com/cook-php">Cook php</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[I regret using PHP]]></title>
            <link>https://medium.com/cook-php/i-regret-using-php-5e0c6c29e493?source=rss-df3d6238cc23------2</link>
            <guid isPermaLink="false">https://medium.com/p/5e0c6c29e493</guid>
            <category><![CDATA[php]]></category>
            <dc:creator><![CDATA[Jorge Castro]]></dc:creator>
            <pubDate>Sat, 25 Sep 2021 15:46:24 GMT</pubDate>
            <atom:updated>2021-09-25T15:46:24.925Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/0*AvlvCwUcMGm_h1jv.png" /></figure><p>I regret using PHP.</p><p>Right now, I finished a titanic project (around 3 year in the making) and the project is working as expected. However, it feels so fragile and I think I loss a lot of time in some other tasks rather than the own code (including testing/benchmarking libraries, creating our own libraries).</p><p>One of the key part of the project is the access to the database, so for this, I use an “orm”. For PHP, you can use any ORM in PHP to do the job, however, this project is not easy and it requires some tricks.</p><p>First, I tried Laravel and the performance of Laravel (because I want to use its ORM) could be resumed in a single word: SLOW. So I rejected it completely. I tested other ORM and they are also really slow, so I created one from scratch with two goals:</p><p>a) simple<br>b) fast.</p><p>And here is the project</p><p><a href="https://github.com/eftec/pdoone">https://github.com/eftec/pdoone</a></p><p>And it works (more or less).</p><h3>Why do I need an ORM?</h3><p>Because it is not possible to create a project using the primitive functionalities of PHP (PDO in this case), example:</p><p>Using PDO<br>(it is prone to mistakes)</p><pre>$stmt = $pdo-&gt;prepare(&quot;SELECT * FROM myTable WHERE name = ?&quot;);<br>$stmt-&gt;bindParam(1,$_POST[&#39;name&#39;],PDO::PARAM_STR);<br>$stmt-&gt;execute();<br>$result = $stmt-&gt;get_result();<br>$products=[];<br>while($row = $result-&gt;fetch_assoc()) {<br>  $product[]=$row; <br>}<br>$stmt-&gt;close();</pre><p>Using my library</p><pre>$products=$pdoOne<br>    -&gt;select(&quot;*&quot;)<br>    -&gt;from(&quot;myTable&quot;)<br>    -&gt;where(&quot;name = ?&quot;,[$_POST[&#39;name&#39;]]) <br>    -&gt;toList();</pre><p>Using my library (ORM)</p><pre>ProductRepo // this class was generated with echo $pdoOne()-&gt;generateCodeClass([&#39;Product&#39;]);<br>    ::where(&quot;name = ?&quot;,[$_POST[&#39;name&#39;]])<br>    ::toList();</pre><p>Then, I found the main problem of PHP: “dynamic typing”.</p><h3>dynamic typing</h3><p>Let’s say we have a function that returns a list of products.</p><pre>$products=ProductRepo::listall();</pre><p>However, PHP does not know if we are returning a list of products. We could add type hinting, but (as its name says), it is just a type hinting/validation and nothing more. Type hinting is a cheap solution and it is not foolproof at all.</p><pre>function listall():array {<br>      // code goes here<br>   }</pre><p>But, there is another problem. PHP doesn’t have the concept of array-of-a-specific-type.</p><p>It is Java:</p><pre>products=new ArrayList&lt;Product&gt;();</pre><p>It is c#</p><pre>products=new List&lt;Product&gt;();</pre><p>And it is PHP</p><pre>$products=array(); // or simply [], so we could store an object, a number or whatever value here.</pre><h3>objects versus array</h3><p>Let’s say we have a model of an invoice.</p><pre>class InvoiceDetails {<br>   public $idInvoiceDetail;<br>   public $idInvoice;<br>   public $product;<br>   public $quantity;<br>}<br>class Invoice {<br>   public $idInvoice;<br>   public $customer;<br>   public $date;<br>   public $invoiceDetails;  // a list of invoicedetails<br>}</pre><p>What if we want to serialize:</p><pre>$invoice=new Invoice(); // $invoice is an instance of Invoice<br>   $json=json_encode($invoice); // $json is the class serialized<br>   $invoiceback=json_decode($json); // now $invoice is an instance of stdclass.</pre><p>We could convert it manually but it takes so much resources to have a correct serialization.</p><p>So, the best solution is to use an associative array. Why?</p><pre>$invoice=[&#39;idinvoice&#39;=&gt;1...]; // $invoice is an array<br>   $json=json_encode($invoice); // $json is the array serialized<br>   $invoiceback=json_decode($json,true); // now $invoice is an array.</pre><p>In PHP, we don’t need to use models at all. We could use a bit of them to get some type hinting but again, it is not a perfect solution, neither it is foolproof or help in a big project. It also kills the performance considerably (mainly if you want to serialize/de-serialize).</p><h3>Are libraries the solution?</h3><p>There are some libraries to help solving those problems. However, they bring new problems: performance. Many PHP libraries use a lot of “hack” solutions to solve the problems of PHP such as serialization, for example using reflections and such. <strong><em>However, they are a minefield and some of them don’t care about the performance at all.</em></strong></p><h3>But why I regret PHP?</h3><p>Let’s say our initial problem, a function that returns a list of products.</p><p>It is PHP</p><pre>$products=ProductRepo::listAll();<br>   // show the first product if any<br>   if($products!==null &amp;&amp; count($products)&gt;0) {<br>      echo $products[0]-&gt;name; // or $products[0][&#39;name&#39;] if array<br>   }</pre><p>There is not warranty that this code will work because the PHP language does not really know that <strong>$products</strong> has a list of products.</p><p>It is c#</p><pre>List&lt;Product&gt; products=ProductoRepo.listAll();<br>   if(products!=null &amp;&amp; products.Count()&gt;0) {<br>      console.log(products[0].name) <br>   }</pre><p>It will always works because c# knows that the variable <strong>products</strong> is a list of products (or null) and there is not other alternative.</p><p>And it is the implementation of the function in c#</p><pre>function listAll() {<br>    var result=new List&lt;Product&gt;();<br>    using(var dbase=new BaseExample()) {<br>        result=dbase.Products.toList();<br>    }<br>    return result;    <br>}</pre><p>It simple and it works. There is not minefield here.</p><p>It uses Entity Framework and it reads from the database, converts the value and returns a list of products. The performance hit is minimum (I tested). Why? First, the system does not need to guess the field (the field exists or it raises an error), it does not need to do type juggling and because C# is a compiled language.</p><p>And it is the serialization/de-serialization</p><pre>string json = JsonSerializer.Serialize(products);<br>var productsdes = JsonSerializer.Deserialize&lt;List&lt;Product&gt;&gt;(json);</pre><p>And again simple and it works or it raises an error (there is not middle ground here).</p><h3>For the records and about the comments</h3><h3>About Swoole</h3><p>I tested Swoole and it works. However, it brings two problems:</p><p>a) It does not work on Windows.</p><p>You can’t whine anything against Windows, but Windows is king for corporate and big companies. It means for example the office suite and other programs such vpn that only works in Windows. My Dev machine is and will be Windows because it works almost all programs (there are 3 exceptions, one of them is Swoole). ps: The second program that does not work in Windows is Docker. There is a version of Docker for Windows but it is a “tiny”-emulator, so it is not a true (lightweight) container but a bulky one (so it breaks the <strong>raisons d’être</strong> of container)</p><p>b) Swoole is not magical. It is not a new PHP runtime engine on steroids, so if PHP is slow then Swoole too. i.e. Swoole works fine in one cases but bad in others. Also, I am not fancy to add more complexity to the code.</p><p>And for this case, C# allows async tasks natively, so we don’t need to runs a separate service so we could multi-task those slow task in a separate thread (and without creating sockets). Microsoft warns us about when we should use it and when don’t because multitasking is not a magic wand that works for every case.</p><h3>Why I use PHP 5.x?</h3><p>No, I don’t. I use PHP 8.0.10. However, I can keep my code syntactically compatible with PHP 5.6 (at least the open source libraries). There are some new syntaxes in PHP 7 and 8 but most of them are syntax sugar, so it is not worth to migrate those public library from 5.6 to 7 or 8. Why?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/469/0*yK_yIDyf8pHSYRvo.png" /></figure><p>However, there are a few useful functions but nothing else much. I like the opcache of PHP &gt;7.0</p><h3>Type hinting</h3><p>One of the new features of PHP 7 is the type hinting and it is another minefield.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/590/0*l-FSPhFSAPXLbZ2m.png" /></figure><p>Why?<br>In PHP, type hinting is also type validation, and it is validated not once but every time the function is called.</p><p><a href="https://github.com/EFTEC/php-benchmarks#type-hinting">https://github.com/EFTEC/php-benchmarks#type-hinting</a></p><pre>// what you write<br>function example(Class $field1): string {</pre><pre>}<br>// what php really does:<br>function example($field1) {<br>    if(!get_type($gettype)!=&#39;Class&#39;) {<br>        throw new Exception(&quot;field incorrect&quot;);<br>    }<br>    // ...    <br>}</pre><p>So it affects the performance. It is not a big deal in most of the code but some functions are called not once but thousand of times per request of the user. For example, if we have a function that takes 0.001 seconds but this function is called 100 times, then, in total it takes 0.1 second, so it is not so bad, but this measure is per request, so if we have 100 concurrent request, then we are taking 10 seconds in total. If we split in 4 cores, then each core is taking 2 seconds and it is not good.</p><p>Luckily, type hinting adds a mere 0.0001 seconds per 5000 requests, however it’s easy to pile up slowness (example, 1000 concurrent users listing 5000 rows and each row calls 1 function)</p><p>I heavily use PHPDOC that it doesn’t impact the performance and it is still more powerful than type hinting. It is not ideal but it is give some balance between performance and hinting.</p><p>Python in this aspect is more straightforward, In Python, type hinting is only that, a hint, not a validation, so its up to the code to validate the code.</p><p>C#: it does not need any of them because the validation is done at compile it, so it is evaluated once, versus PHP that it is evaluated for each call.</p><h3>Psalm and PHPStan.</h3><p>Both are nice libraries but again, they are not for free (they add a new “compile stage”). However, they don’t do magic either, they are unable to detect all if not common problems while it forces us to work (for some tasks) in some very precise task.<br>But, I skip them because <strong>PHPStorm</strong> does many of the tasks of both without slowing the development process.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/880/0*D4qtwEpxAtVceBYs.png" /></figure><p>But again, both libraries are not even able to determine the right type of field of a variable (if the variable is enough complex).</p><p>About C#. C# has some libraries that do the same job. However, Visual Studio (not code) also do a superb detecting problems right out of the bat, but it also allows refactoring.</p><h3>In general.</h3><p>PHP is not a bad language. If you look at Python and Django (or Ruby and Rails), PHP is miles better but it is still trying to play a catching-up game with the big guys (Java and C#) then no.</p><p>PHP is playing a game of be a dynamic typed language while it tries to simulate a static typed language. Maybe PHP needs to forks itself and create a new static type language.</p><h3>PHP and Impostor Syndrome</h3><p>It is what I have seen</p><pre>class Customer {<br>     private $id;<br>     private $name;<br>     public function setId(int $id) {<br>        $this-&gt;id=$id;<br>     }<br>    public function getId():int {<br>        return $this-$id;<br>    }<br>}</pre><p>What is the problem with it? The performance of this piece of code is awful. Java could work with this kind of code because Java optimizes the setter and getters. PHP doesn’t have such feature.</p><p>And about Laravel, it is a model:</p><pre>class Customer extends Models {</pre><pre>}<br>// O_O</pre><p>So we should guess the fields of customer. We could add some hinting and default values but nothing else much. Also, this model relies in some nasty reflection (__set method). Since Laravel is based in this of code and the model is the core of every functionality of the code, then it is the reason why it is slow.</p><p>And Symphony is not better, for example the use of YAML (it has some alternatives)</p><pre>Article:<br>  actAs: [Timestampable]<br>  tableName: blog_article<br>  columns:<br>    id:<br>      type: integer<br>      primary: true<br>      autoincrement: true<br>    title:   string(255)<br>    content: clob</pre><p>And Wordpress is not any better</p><pre>$customers=[&#39;id&#39;=1,&#39;name&#39;=&gt;&#39;john&#39;];</pre><p>However, it gives the best performance and it is more straightforward. However, it will be hard to maintenance.</p><h3>But why C</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/880/0*iJpMKVAaiTTEVxdR.png" /></figure><p>Of course, it does not show the whole picture, for example, servers that doesn’t divulge the technology used.</p><p>Also, for employment in USA</p><ul><li>python 176k jobs</li><li>java 142k jobs</li><li>javascript 119k jobs</li><li>c# 83k jobs</li><li>php 15k jobs</li></ul><p>But again, it is just another measure that it is not complete. For example, Python is more popular than Java, but a Java developer lasts more in a job (the projects are more longest and well paid).</p><p>However, why PHP is the more popular (in public websites) and, at the same time, one of the least popular language (in jobs).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/0*D-IfTp2TTcmEVtNm.png" /></figure><h3>For the note:</h3><p>Many developers have a mis-conception of performance and usability. Example: “my code is slow, however, if I add some framework or library, then it automatically will run better”. Some libraries, specially frameworks, are not performance-wise. They are more focused in stability, validation and general use (and some of them are mainly syntax sugar over anything else).</p><p>In Laravel, it is what we do to assign a field:</p><pre>$object-&gt;field=&#39;hello&#39;;</pre><p>However, the framework does:</p><ul><li>it validates if the field has mutators. If yes, then it applies it.</li><li>it validates if the field is date</li><li>it validates if the field is cast callable.</li><li>it validates if the field is json castable</li><li>it validates if the field is encrypt castable</li><li>and finally, it assigns the value to an inner array.</li></ul><p>And when it validades if the field has mutators, it calls the method studly</p><pre>public static function studly($value)<br>    {<br>        $key = $value;</pre><pre>        if (isset(static::$studlyCache[$key])) {<br>            return static::$studlyCache[$key];<br>        }</pre><pre>        $value = ucwords(str_replace([&#39;-&#39;, &#39;_&#39;], &#39; &#39;, $value));</pre><pre>        return static::$studlyCache[$key] = str_replace(&#39; &#39;, &#39;&#39;, $value);<br>    }</pre><p>Every time.</p><p>What is the problem</p><pre>for($i=0;$i&lt;10000;$i++) {<br>   $object[$i]-&gt;field=&#39;hello&#39;; // bye bye performance<br>}</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5e0c6c29e493" width="1" height="1" alt=""><hr><p><a href="https://medium.com/cook-php/i-regret-using-php-5e0c6c29e493">I regret using PHP</a> was originally published in <a href="https://medium.com/cook-php">Cook php</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[PHP, Benchmark time]]></title>
            <link>https://medium.com/cook-php/php-benchmark-time-fc19d813aa98?source=rss-df3d6238cc23------2</link>
            <guid isPermaLink="false">https://medium.com/p/fc19d813aa98</guid>
            <category><![CDATA[php-developers]]></category>
            <category><![CDATA[benchmark]]></category>
            <category><![CDATA[php]]></category>
            <dc:creator><![CDATA[Jorge Castro]]></dc:creator>
            <pubDate>Sat, 24 Jul 2021 23:18:51 GMT</pubDate>
            <atom:updated>2021-07-24T23:18:51.860Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/0*gG1FcLJE3h2vybWa.jpg" /></figure><h3>Benchmark array versus object</h3><p>This benchmark tests the next functionalities:</p><ul><li>Create a variable.</li><li>Then, it reads a simple value</li><li>And it adds to the list (the list is created every round)</li></ul><p>And it is an example of the variables used</p><pre>$array_numeric=[$hello,$second,$third];</pre><pre>$array_not_numeric=[&#39;hello&#39;=&gt;$hello,&#39;second&#39;=&gt;$second,&#39;third&#39;=&gt;$third];</pre><pre>$object_constructor=DummyClass(&#39;world&#39;,0,20.3);</pre><pre>$object_no_constructor=new DummyClass2();<br>$object_no_constructor-&gt;hello=&#39;world&#39;;<br>$object_no_constructor-&gt;second=0;<br>$object_no_constructor-&gt;third=20.3;</pre><p>We also test the use of factory, constructor, setter and getters, stdClass and magic methods.</p><p>What is a factory? A factory is a function used for creating an entity (in this case, an array).</p><p>what is a constructor? A constructor is part of a class and is used to initialize the instance of the object.</p><h3>Result (smaller is better)</h3><p>It is the result of the benchmarks in seconds</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8uuTf5rsOJEW0WFsEM5vLA.png" /></figure><h3>Result in percentage compared with the smaller result.</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MURpEW_VB5-SIIqY3Fg-hg.png" /></figure><p>Conclusion:</p><ul><li>The difference between an array numeric and an associative array is a mere 5%, so you can say that they are the same.</li><li>The use of an object is +100% slower but it is still acceptable in most conditions (aka it uses the double of time).</li><li>The call to a method or the use of a constructor increases the value considerably. <strong>Also, it’s better to use an object/constructor than an array/factory.</strong> Why? I don’t know.</li><li>The use of setter/getters impacts the performance considerably. If you can then you should avoid that.</li><li>The use of magic setters and getters is horrible (almost 10 times slower). Is it the reason why Laravel is slow?</li><li>Also, the setters and getters are vanilla, they don’t validate if the field exists of any other validation.</li><li>And the use of a <strong>stdClass</strong> (anonymous class) is also bad but not as bad as to use setter and getters.</li></ul><p>ps: The test ran 1 million times and the difference is smaller than 0.3 seconds, so is it important?</p><p>Let’s say we have 100 concurrent users (not a small number but not impossible), and we are processing and returning a list with 1000 values. It is 100x1000 = 100&#39;000 objects. So, if we consider 100&#39;000 objects, then the difference is less than 0.03 seconds in the worst case. However, our systems process more than a single operation, so if we are showing a list of objects, then we also validating, showing other values, validating, reading from the database and storing into the memory and returning to the customer via a web or serialized, so this value could considerable and the use of the CPU is on-top of other processes. It is not a big deal for a small project, but it is important for a big project.</p><p>tl/dr</p><pre>$customer[0]=&#39;john&#39;; // faster but it is hard to understand<br>$customer[&#39;name&#39;]=&#39;john&#39;; // almost as fast as the first one but it is clear to understand (it also uses more memory)<br>$customer-&gt;name=&#39;john&#39;; // (where $customer is an object of the class Customer) slower but it still acceptable.<br>$customer-&gt;name=&#39;john&#39;; // (where $customer is an object of the class stdClass) the double of slower than to use a class. <br>$customer=new Customer(&#39;john&#39;); // (constructor) even slower but is still acceptable;<br>$customer=factory(&#39;john&#39;); // (where factory is an array that returns an array). Slower than the use of constructor.<br>$customer-&gt;setName(&#39;john&#39;); // bad performance<br>$customer-&gt;name=&#39;john&#39;; // (where the class uses a magic method) awful performance, avoid this one.</pre><p>The code is here (if you want to test it)</p><p><a href="https://github.com/EFTEC/php-benchmarks/blob/master/benchmark_array_vs_object.php">https://github.com/EFTEC/php-benchmarks/blob/master/benchmark_array_vs_object.php</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fc19d813aa98" width="1" height="1" alt=""><hr><p><a href="https://medium.com/cook-php/php-benchmark-time-fc19d813aa98">PHP, Benchmark time</a> was originally published in <a href="https://medium.com/cook-php">Cook php</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>