<?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: Andrea Olivato</title>
    <description>The latest articles on DEV Community by Andrea Olivato (@andreaolivato).</description>
    <link>https://dev.to/andreaolivato</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%2F534493%2Fd766a063-55a3-4a54-9467-40326c284cee.jpeg</url>
      <title>DEV Community: Andrea Olivato</title>
      <link>https://dev.to/andreaolivato</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/andreaolivato"/>
    <language>en</language>
    <item>
      <title>How you write your String matters: benchmarking PHP</title>
      <dc:creator>Andrea Olivato</dc:creator>
      <pubDate>Fri, 09 Jul 2021 16:01:51 +0000</pubDate>
      <link>https://dev.to/andreaolivato/how-you-write-your-string-matters-benchmarking-php-dlf</link>
      <guid>https://dev.to/andreaolivato/how-you-write-your-string-matters-benchmarking-php-dlf</guid>
      <description>&lt;p&gt;There are a lot of ways in which you can specify, use and print  &lt;a href="https://www.php.net/manual/en/language.types.string.php" rel="noopener noreferrer"&gt;string in PHP&lt;/a&gt;. They all have different benefits and drawbacks and that's not the content of this article. The focus of these tests is to determine how using different string specifications affects the performances of your PHP code.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;TL;DR: Single quoted strings are the most performing, both for simple text and for concatenation with other variables.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Tests
&lt;/h2&gt;

&lt;p&gt;Compared 3 types of string specification:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single Quoted (e.g. &lt;code&gt;echo 'string';&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Double Quoted (e.g. &lt;code&gt;echo "string";&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;HEREDOC (e.g. &lt;code&gt;echo &amp;lt;&amp;lt;&amp;lt;EOT string EOT;&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For each type of specification, 2 tests:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple string (e.g. &lt;code&gt;'string'&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;String + a variable (e.g. &lt;code&gt;'string'.$var&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Iterations
&lt;/h2&gt;

&lt;p&gt;In order to simulate a strong workload and have more data, the code ran 10 iterations with a 5-second pause. For each iteration 1 Million &lt;code&gt;echo&lt;/code&gt; were executed, without any pause.&lt;/p&gt;

&lt;p&gt;To make sure that the machine load doesn't skew the results, all the 3 different specifications are executed within the same iteration, one after the other, with the same 5-second delay. So at any point in time, the load should be equally distributed among the different specifications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Buffer
&lt;/h2&gt;

&lt;p&gt;Since the actual printing of the strings must not affect these tests, &lt;code&gt;ob_start()&lt;/code&gt; and &lt;code&gt;ob_end_clean()&lt;/code&gt; are used to not print anything, and &lt;code&gt;ob_clean()&lt;/code&gt; is used within each iteration to free up the buffer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Code
&lt;/h2&gt;

&lt;p&gt;This is the code used to run the tests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="nb"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'MAX_PER_ITERATION'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10000000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'MAX_ITERATIONS'&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="nb"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'SLEEP_TIME'&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="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"TEST 1: Simple String&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$times&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'quote'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="s1"&gt;'doublequote'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="s1"&gt;'heredoc'&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;$k&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="no"&gt;MAX_ITERATIONS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;$k&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="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Iteration "&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cm"&gt;/* Start Single Quote tests */&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;Quote&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&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="nv"&gt;$start&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;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;MAX_PER_ITERATION&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nb"&gt;ob_clean&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;$diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&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="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;$start&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="nv"&gt;$times&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'quote'&lt;/span&gt;&lt;span class="p"&gt;][]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$diff&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="no"&gt;SLEEP_TIME&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="cm"&gt;/* Start Double Quote tests */&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;Double Quote&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&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="nv"&gt;$start&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;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;MAX_PER_ITERATION&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nb"&gt;ob_clean&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;$diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&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="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;$start&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="nv"&gt;$times&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'doublequote'&lt;/span&gt;&lt;span class="p"&gt;][]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$diff&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="no"&gt;SLEEP_TIME&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="cm"&gt;/* Start HEREDOC tests */&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;Heredoc&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&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="nv"&gt;$start&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;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;MAX_PER_ITERATION&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;EOT&lt;/span&gt;
            &lt;span class="n"&gt;string&lt;/span&gt;
        &lt;span class="no"&gt;EOT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nb"&gt;ob_clean&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;$diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&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="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;$start&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="nv"&gt;$times&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'heredoc'&lt;/span&gt;&lt;span class="p"&gt;][]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$diff&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="no"&gt;SLEEP_TIME&lt;/span&gt;&lt;span class="p"&gt;);&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;$times&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$type&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$results&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="nv"&gt;$type&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&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;$results&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$r&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;"&lt;/span&gt;&lt;span class="se"&gt;\t\t&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;$avg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nb"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$results&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;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;Avg: "&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$avg&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"TEST 2: String with Variable&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$times&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'quote'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="s1"&gt;'doublequote'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="s1"&gt;'heredoc'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nv"&gt;$variable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'string2'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;$k&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="no"&gt;MAX_ITERATIONS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;$k&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="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Iteration "&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cm"&gt;/* Start Single Quote tests */&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;Quote&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&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="nv"&gt;$start&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;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;MAX_PER_ITERATION&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$variable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nb"&gt;ob_clean&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;$diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&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="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;$start&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="nv"&gt;$times&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'quote'&lt;/span&gt;&lt;span class="p"&gt;][]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$diff&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="no"&gt;SLEEP_TIME&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="cm"&gt;/* Start Double Quote tests */&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;Double Quote&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&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="nv"&gt;$start&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;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;MAX_PER_ITERATION&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"string &lt;/span&gt;&lt;span class="nv"&gt;$variable&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nb"&gt;ob_clean&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;$diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&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="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;$start&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="nv"&gt;$times&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'doublequote'&lt;/span&gt;&lt;span class="p"&gt;][]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$diff&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="no"&gt;SLEEP_TIME&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="cm"&gt;/* Start HEREDOC tests */&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;Heredoc&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&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="nv"&gt;$start&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;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;MAX_PER_ITERATION&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;EOT&lt;/span&gt;
            &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$variable&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="no"&gt;EOT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nb"&gt;ob_clean&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;$diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&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="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;$start&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="nv"&gt;$times&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'heredoc'&lt;/span&gt;&lt;span class="p"&gt;][]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$diff&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="no"&gt;SLEEP_TIME&lt;/span&gt;&lt;span class="p"&gt;);&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;$times&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$type&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$results&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="nv"&gt;$type&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&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;$results&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$r&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;"&lt;/span&gt;&lt;span class="se"&gt;\t\t&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;$avg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nb"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$results&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;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;Avg: "&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$avg&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary Results
&lt;/h2&gt;

&lt;p&gt;Unsurprisingly, the &lt;strong&gt;Single Quoted strings are the fastest&lt;/strong&gt;: as they don't require parsing for variables or special characters (e.g. &lt;code&gt;\n&lt;/code&gt;), they run quicker than the others both for simple strings and for variables.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple String: &lt;code&gt;0.3838947773&lt;/code&gt; seconds for 1 Million executions&lt;/li&gt;
&lt;li&gt;String+Variable: &lt;code&gt;0.532834816&lt;/code&gt; seconds for 1 Million executions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Heredoc&lt;/strong&gt; performs a bit slower than Single Quoted strings, but faster than Double Quoted ones, especially when without variables.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple String: &lt;code&gt;0.387871933&lt;/code&gt; seconds for 1 Million executions&lt;/li&gt;
&lt;li&gt;String+Variable: &lt;code&gt;0.553892827&lt;/code&gt; seconds for 1 Million executions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally &lt;strong&gt;Double Quoted&lt;/strong&gt; strings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple String: &lt;code&gt;0.3914105415&lt;/code&gt; seconds for 1 Million executions&lt;/li&gt;
&lt;li&gt;String+Variable: &lt;code&gt;0.5623492718&lt;/code&gt; seconds for 1 Million executions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Complete Results
&lt;/h2&gt;

&lt;p&gt;Below you can see a sneak peak of the final results. If you click on the image or  &lt;a href="https://docs.google.com/spreadsheets/d/1D381g94mJwLDyUt8gqXf4A4l_RSYD1sHfaQ5g97f8J8/edit?usp=sharing" rel="noopener noreferrer"&gt;here&lt;/a&gt; , you can access a shared spreadsheet with the complete data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.google.com/spreadsheets/d/1D381g94mJwLDyUt8gqXf4A4l_RSYD1sHfaQ5g97f8J8/edit?usp=sharing" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625845740107%2FXcI6Qh9Ih.png" alt="Screenshot 2021-07-09 at 11.39.27 PM.png"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  System/Versions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;PHP 7.4.19&lt;/li&gt;
&lt;li&gt;Amazon Linux 2 AMI &lt;/li&gt;
&lt;li&gt;Kernel 4.14.232-177.418.amzn2.x86_64&lt;/li&gt;
&lt;li&gt;16GB Memory&lt;/li&gt;
&lt;li&gt;4 Virtual CPUs&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>php</category>
      <category>benchmark</category>
      <category>performance</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Fix `ld: library not found for -lgomp` when installing Imagick 3.5 via PHP pecl on Mac</title>
      <dc:creator>Andrea Olivato</dc:creator>
      <pubDate>Mon, 21 Jun 2021 06:14:43 +0000</pubDate>
      <link>https://dev.to/andreaolivato/fix-ld-library-not-found-for-lgomp-when-installing-imagick-3-5-via-php-pecl-on-mac-488n</link>
      <guid>https://dev.to/andreaolivato/fix-ld-library-not-found-for-lgomp-when-installing-imagick-3-5-via-php-pecl-on-mac-488n</guid>
      <description>&lt;h2&gt;
  
  
  Update 25 July 2021
&lt;/h2&gt;

&lt;p&gt;As of 22 July 2021, version 3.5.1 is stable in the &lt;code&gt;pecl&lt;/code&gt; channel and can be used to compile &lt;code&gt;imagick&lt;/code&gt; for both PHP 7 and PHP 8.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;The general command will not fail anymore&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Install the older version (3.4.4) of Imagick forcing it via &lt;code&gt;pecl&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;The last version (3.5) of the PHP extension for Imagemagick ( &lt;a href="https://github.com/Imagick/imagick"&gt;Imagick&lt;/a&gt; ) introduces a compilation error on Apple systems, which is independent from the PHP version (tested on 7.4 and 8) and Imagemagick version (tested on 6.x and 7.x) and is instead related to the missing/broken support for  &lt;a href="https://gcc.gnu.org/projects/gomp/"&gt;gomp&lt;/a&gt; of the gcc compiler.&lt;/p&gt;

&lt;p&gt;This is not related to Apple Silicon either, as I've tested on an Intel machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Error
&lt;/h2&gt;

&lt;p&gt;The error is thrown while compiling, after running&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;The complete error is&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ld: library not found for -lgomp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Potential Fixes
&lt;/h2&gt;

&lt;p&gt;There are several Stack Overflow threads talking about compilation errors due to Gomp. The most comprehensive I've found  &lt;a href="https://stackoverflow.com/questions/20321988/error-enabling-openmp-ld-library-not-found-for-lgomp-and-clang-errors"&gt;is this&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;I've tried few of the fixes proposed in the answer, but most require compiling a different version of gcc,  which would make subsequent updates via homebrew unstable.&lt;/p&gt;

&lt;p&gt;Also tried this other  &lt;a href="https://stackoverflow.com/questions/43555410/enable-openmp-support-in-clang-in-mac-os-x-sierra-mojave/48746939#48746939"&gt;amazing thread&lt;/a&gt; on Stack Overflow which suggests &lt;code&gt;llvm&lt;/code&gt; and revised compiler flags, but it didn't work for this specific case, probably due to built-in parameters in the pecl compilation process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Actual Fix
&lt;/h2&gt;

&lt;p&gt;In the end the final fix was to downgrade the version of Imagick to 4.3.3, which compiles perfectly.&lt;/p&gt;

&lt;p&gt;You can do so either by  &lt;a href="https://github.com/Imagick/imagick/releases/tag/3.4.4"&gt;downloading the release&lt;/a&gt;  from github or simply by forcing the version in pecl as follows:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



</description>
      <category>php</category>
      <category>pecl</category>
      <category>mac</category>
      <category>imagemagick</category>
    </item>
    <item>
      <title>Retrieve Video List from the official TikTok APIs</title>
      <dc:creator>Andrea Olivato</dc:creator>
      <pubDate>Thu, 03 Jun 2021 04:11:11 +0000</pubDate>
      <link>https://dev.to/andreaolivato/retrieve-video-list-from-the-official-tiktok-apis-2loe</link>
      <guid>https://dev.to/andreaolivato/retrieve-video-list-from-the-official-tiktok-apis-2loe</guid>
      <description>&lt;p&gt;The &lt;a href="https://github.com/andreaolivato/TikTok-LoginKit-PHP"&gt;TikTok PHP SDK&lt;/a&gt; has been updated, and the new &lt;a href="https://github.com/andreaolivato/TikTok-LoginKit-PHP/releases/tag/v0.2"&gt;v0.2&lt;/a&gt; brings support for retrieving the User’s Videos.&lt;/p&gt;

&lt;p&gt;If you’re new to the TikTok PHP SDK, please read my &lt;a href="https://dev.to/andreaolivato/how-to-implement-the-tiktok-login-kit-for-web-in-php-2161"&gt;previous tutorial&lt;/a&gt; on how to log in and receive the Access Token. In that article, I also provide a bit of backstory and more general information about the TikTok Login Kit APIs for Web.&lt;br&gt;
Once you’re all caught up and know how to log in and retrieve the access Token, retrieving the Videos is blazing fast.&lt;/p&gt;

&lt;p&gt;The easiest way is to use the &lt;code&gt;getUserVideoPages&lt;/code&gt; helper method, since it provides built-in pagination.&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;$videos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$_TK&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getUserVideoPages&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will return an array that contains all the videos of the logged in user. Watch out because this will keep looping and calling the APIs for all the videos you have. So you might want to add the &lt;code&gt;max_pages&lt;/code&gt; parameter. For example to limit to the latest 10 pages only:&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;$videos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$_TK&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getUserVideoPages&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want more control over the pagination, you can use the higher-level &lt;code&gt;getUserVideos&lt;/code&gt; method, which allows you to manage your own pagination via the &lt;code&gt;cursor&lt;/code&gt; and &lt;code&gt;num_results&lt;/code&gt; parameters. For example, let’s say you only want the latest video:&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;$videos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$_TK&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getUserVideos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The pagination info is provided in the &lt;code&gt;cursor&lt;/code&gt; and &lt;code&gt;has_more&lt;/code&gt; returned values. &lt;/p&gt;

&lt;p&gt;Here’s how you can implement your own pagination:&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;$videos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="nv"&gt;$cursor&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;$count_pages&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;$max_pages&lt;/span&gt; &lt;span class="o"&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;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$vids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getUserVideos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$cursor&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_pages&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="nv"&gt;$count_pages&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$max_pages&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$max_pages&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&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;$vids&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'videos'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$videos&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$v&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;$vids&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'has_more'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$cursor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$vids&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'cursor'&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;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you have your &lt;code&gt;$videos&lt;/code&gt; you can use the simple getter methods, for example &lt;code&gt;getCoverImageURL&lt;/code&gt; to get all the available parameters.&lt;/p&gt;

&lt;p&gt;Here’s a quick sample, populating a table&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$videos&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nv"&gt;$trs&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;&amp;lt;&amp;lt;&amp;lt;HTML
       &amp;lt;tr&amp;gt;
           &amp;lt;td width="100"&amp;gt;&amp;lt;img src="{$v-&amp;gt;getCoverImageURL()}" style="width:100%"&amp;gt;&amp;lt;/td&amp;gt;
           &amp;lt;td width="100"&amp;gt;
               &amp;lt;strong&amp;gt;ID&amp;lt;/strong&amp;gt;: {$v-&amp;gt;getID()}&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;
               &amp;lt;strong&amp;gt;URL&amp;lt;/strong&amp;gt;: {$v-&amp;gt;getShareURL()}&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;
               &amp;lt;strong&amp;gt;Caption&amp;lt;/strong&amp;gt;: {$v-&amp;gt;getVideoDescription()}
           &amp;lt;/td&amp;gt;
       &amp;lt;/tr&amp;gt;
HTML;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All done! If you have any suggestion on the class or its implementation please feel free to reach out on &lt;a href="https://github.com/andreaolivato/TikTok-LoginKit-PHP"&gt;GitHub&lt;/a&gt; or &lt;a href="https://twitter.com/andreaolivato"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>php</category>
      <category>tiktok</category>
      <category>api</category>
      <category>composer</category>
    </item>
    <item>
      <title>How to implement the TikTok Login Kit for Web in PHP</title>
      <dc:creator>Andrea Olivato</dc:creator>
      <pubDate>Sun, 30 May 2021 10:11:48 +0000</pubDate>
      <link>https://dev.to/andreaolivato/how-to-implement-the-tiktok-login-kit-for-web-in-php-2161</link>
      <guid>https://dev.to/andreaolivato/how-to-implement-the-tiktok-login-kit-for-web-in-php-2161</guid>
      <description>&lt;p&gt;&lt;a href="https://www.tiktok.com/"&gt;TikTok&lt;/a&gt; has recently released their new API to allow Social Login via their platform. They called it &lt;a href="https://developers.tiktok.com/doc/login-kit-web"&gt;Login Kit for Web&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With more Gen-Z and Millennials in the platform, allowing the simplified signup and login process via TikTok is the logical step for many Web Apps, including our very own &lt;a href="https://lnk.bio/"&gt;Lnk.Bio&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While the implementation is a very basic oauth2 flow, there were no published class nor guides specific to PHP implementation, so I thought useful to publish an &lt;a href="https://github.com/andreaolivato/TikTok-LoginKit-PHP"&gt;Open-source class&lt;/a&gt; and this quick tutorial based on such class.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Register your App
&lt;/h2&gt;

&lt;p&gt;First of all, you need to register in the &lt;a href="https://developers.tiktok.com/"&gt;TikTok Developers platform&lt;/a&gt;. Process is easy and approval is quite fast; it took us just 24hrs to get approved with Lnk.Bio](&lt;a href="https://lnk.bio/"&gt;https://lnk.bio/&lt;/a&gt;).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pay attention to the approved redirect URLs. While the TikTok page calls them “Redirect Domains”, they actually require full URLs, so the full path of the page where you’re redirected after the TikTok login.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After you register your application you will receive, as usual a &lt;strong&gt;Client Key&lt;/strong&gt; and &lt;strong&gt;Client Secret&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Install helper class
&lt;/h2&gt;

&lt;p&gt;Use Composer to install the PHP helper&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer require gimucco/tiktok-loginkit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If, for any reason, you’re not using Composer, you can download the class from &lt;a href="https://github.com/andreaolivato/TikTok-LoginKit-PHP/releases/tag/v0.1"&gt;Github&lt;/a&gt;. Current stable is v0.1.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Full Login Example
&lt;/h2&gt;

&lt;p&gt;The login flow is typical:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generate a Redirect Url to send the user to TikTok to authorise your app&lt;/li&gt;
&lt;li&gt;Receive the Authorisation Token&lt;/li&gt;
&lt;li&gt;Exchange the Authorisation Token with an Access Token that you can use for the rest of the calls&lt;/li&gt;
&lt;li&gt;Make a sample call to retrieve the User Information&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s a quick code sample&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nb"&gt;session_start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Important! Required for STATE Variable check and prevent CSRF attacks&lt;/span&gt;
&lt;span class="k"&gt;require_once&lt;/span&gt; &lt;span class="k"&gt;__DIR__&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'/../../../autoload.php'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;gimucco\TikTokLoginKit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Your API Key, as obtained from TikTok Developers portal&lt;/span&gt;
&lt;span class="nv"&gt;$api_secret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Your API Secret, as obtained from TikTok Developers portal&lt;/span&gt;
&lt;span class="nv"&gt;$redirect_uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Where to return after authorization. Must be approved in the TikTok Developers portal&lt;/span&gt;
&lt;span class="nv"&gt;$_TK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TikTokLoginKit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$api_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$api_secret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$redirect_uri&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="nc"&gt;TikTokLoginKit\Connector&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;receivingResponse&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// Check if you're receiving the Authorisation Code&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;$token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$_TK&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;verifyCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$_GET&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;TikTokLoginKit\Connector&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;CODE_PARAM&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// Verify the Authorisation code and get the Access Token&lt;/span&gt;

        &lt;span class="c1"&gt;// ** Your logic to store the access token goes here&lt;/span&gt;


        &lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$_TK&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Retrieve the User Object&lt;/span&gt;

        &lt;span class="c1"&gt;// ** Your logic to store or use the User Info goes here&lt;/span&gt;

        &lt;span class="c1"&gt;// Print some HTML as example&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="sh"&gt;&amp;lt;&amp;lt;&amp;lt;HTML
        &amp;lt;table width="500"&amp;gt;
            &amp;lt;tr&amp;gt;
                &amp;lt;td with="200"&amp;gt;&amp;lt;img src="{$user-&amp;gt;getAvatarLarger()}"&amp;gt;&amp;lt;/td&amp;gt;
                &amp;lt;td&amp;gt;
                    &amp;lt;br /&amp;gt;
                    &amp;lt;strong&amp;gt;ID&amp;lt;/strong&amp;gt;: {$user-&amp;gt;getOpenID()}&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;
                    &amp;lt;strong&amp;gt;Name&amp;lt;/strong&amp;gt;: {$user-&amp;gt;getDisplayName()}
                &amp;lt;/td&amp;gt;
            &amp;lt;/tr&amp;gt;
        &amp;lt;/table&amp;gt;
HTML;&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;Exception&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: "&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getMessage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;br /&amp;gt;&amp;lt;a href="?"&amp;gt;Retry&amp;lt;/a&amp;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="c1"&gt;// Print the initial login button that redirects to TikTok&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;a href="'&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$_TK&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getRedirect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'"&amp;gt;Log in with TikTok&amp;lt;/a&amp;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;All done! If you have any suggestion on the class or its implementation please feel free to reach out on &lt;a href="https://github.com/andreaolivato/TikTok-LoginKit-PHP"&gt;GitHub&lt;/a&gt; or &lt;a href="https://twitter.com/andreaolivato"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>php</category>
      <category>github</category>
      <category>tiktok</category>
      <category>composer</category>
    </item>
    <item>
      <title>Distinguish between Business and Creators with the Instagram Graph API
</title>
      <dc:creator>Andrea Olivato</dc:creator>
      <pubDate>Sat, 22 May 2021 08:41:19 +0000</pubDate>
      <link>https://dev.to/andreaolivato/distinguish-between-business-and-creators-with-the-instagram-graph-api-2ama</link>
      <guid>https://dev.to/andreaolivato/distinguish-between-business-and-creators-with-the-instagram-graph-api-2ama</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;TL;DR: Use Try/Catch on an empty Content Publishing call and look for a specific exception code to differentiate between Business and Creators accounts.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you use the new &lt;a href="https://developers.facebook.com/docs/instagram-api/"&gt;Instagram Graph API&lt;/a&gt; (not to be confused with the &lt;a href="https://developers.facebook.com/docs/instagram-basic-display-api/"&gt;Instagram Basic Display API&lt;/a&gt;) you know that these APIs can be used by Instagram Business Accounts and Creators Accounts.&lt;/p&gt;

&lt;p&gt;Until recently, the difference between the two didn’t matter as much, since most features are available to both groups. However, when the new &lt;a href="https://developers.facebook.com/docs/instagram-api/guides/content-publishing/"&gt;Instagram Content Publishing Api&lt;/a&gt; was released, Facebook made it only available for Business Accounts, not Creators.&lt;/p&gt;

&lt;p&gt;This means that an Instagram Creator can Log In via Facebook and allow the permission for Content Publishing; but when you actually try to publish the content on their page, the API will throw an exception, saying that the user is not allowed to do so.&lt;/p&gt;

&lt;p&gt;The main concern we encountered for &lt;a href="https://lnk.bio/"&gt;Lnk.Bio&lt;/a&gt; is that we need to immediately inform the user that they won’t be able to use this specific feature. Otherwise they might start scheduling the posts for the future and we wouldn’t actually be able to publish them.&lt;/p&gt;

&lt;p&gt;At first, we thought this information would be readily available within the &lt;a href="https://developers.facebook.com/docs/instagram-api/reference/ig-user/"&gt;IG User&lt;/a&gt; object, returned when you query the Instagram Graph API asking information about the logged user. However this endpoint doesn’t contain any information about the account type (Business/Creator). What makes this even stranger is that instead the Instagram Basic Display API provide this information in the &lt;code&gt;account_type&lt;/code&gt; field of the &lt;a href="https://developers.facebook.com/docs/instagram-basic-display-api/reference/user"&gt;User Object&lt;/a&gt;. The returned value can be one of BUSINESS, MEDIA_CREATOR, or PERSONAL, which is exactly what we were looking for. I can’t really find a reason why this is available in the Basic Display API and not the Graph API.&lt;/p&gt;

&lt;p&gt;Looking at &lt;a href="https://stackoverflow.com/questions/57306647/is-there-a-way-to-tell-if-its-an-instagram-creator-or-business-account?noredirect=1#comment119514442_57306647"&gt;StackOverflow&lt;/a&gt; it looked like the most common approach for the Graph API is to &lt;a href="https://stackoverflow.com/a/58806624/1529324"&gt;scrape the user profile&lt;/a&gt;, since this information is published in the page JSON. But this is of course not allowed by Instagram T&amp;amp;C and is also not a solid solution, as it would be subject to network pitfalls, page errors, and also Instagram anti-crawler policy that would block your IPs after too many requests. So this was a no go.&lt;/p&gt;

&lt;p&gt;In the end the best solution we found is to perform an empty POST request simulating the publishing of an Instagram content to the connected account, catch the exception and look for a specific Exception Code 10 in order to identify the type of account.&lt;/p&gt;

&lt;p&gt;In order not to actually publish or create anything on the user account, you can perform an empty call (POST method without any POST data) to the /userid/media endpoint. Then catch the FacebookResponseException and look for the code=10.&lt;/p&gt;

&lt;p&gt;In PHP code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public function isBusiness() {
    try {
        $this-&amp;gt;conn-&amp;gt;post("/".$this-&amp;gt;fb_id."/media", [], $this-&amp;gt;getToken());
        return true;
    } catch (FacebookResponseException $e) {
        if ($e-&amp;gt;getCode() == 10) {
        return false;
    } catch (\Exception $e) {
        return true;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see from the code above, all other exceptions are interpreted as Business Account, while only the Exception with code 10 is interpreted as Creator Account.&lt;/p&gt;

&lt;p&gt;If you have a better approach to this without performing any call, let me know in the comments!&lt;/p&gt;

</description>
      <category>php</category>
      <category>graphql</category>
    </item>
    <item>
      <title>Websocket and Protobuf integration in Javascript</title>
      <dc:creator>Andrea Olivato</dc:creator>
      <pubDate>Fri, 22 Jan 2021 15:32:39 +0000</pubDate>
      <link>https://dev.to/andreaolivato/websocket-and-protobuf-integration-in-javascript-3m5p</link>
      <guid>https://dev.to/andreaolivato/websocket-and-protobuf-integration-in-javascript-3m5p</guid>
      <description>&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API"&gt;WebSockets&lt;/a&gt; are incredibly performing when you need a continuous dialogue between the Frontend and the Backend of an application.&lt;/p&gt;

&lt;p&gt;If you combine them with &lt;a href="https://developers.google.com/protocol-buffers"&gt;Protobuf&lt;/a&gt; to structure the message exchange, you have a great combination for near-realtime data exchange.&lt;/p&gt;

&lt;p&gt;I’ve recently found myself in need to integrate a remote WebSocket with Protobuf directly in the frontend, without using a backend to elaborate the data, in order to be faster and avoid server load.&lt;/p&gt;

&lt;p&gt;While the integration was quite easy, I had troubles finding a good documented tutorial from start to end for frontend (no Node.JS or similar), so here we are.&lt;/p&gt;

&lt;h2&gt;
  
  
  Libraries and Dependancies
&lt;/h2&gt;

&lt;p&gt;I am using the vanilla implementation of WebSocket in Javascript, without any external libraries, so nothing to include there.&lt;/p&gt;

&lt;p&gt;We only need a Protobuf implementation in Javascript, and my choice was &lt;a href="https://github.com/protobufjs/protobuf.js"&gt;ProtobufJS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Easiest way is to use &lt;code&gt;npm&lt;/code&gt; to maintain ProtobufJS, or if you prefer you can use a free CDN&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script src="//cdn.rawgit.com/dcodeIO/protobuf.js/6.X.X/dist/protobuf.min.js"&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the time of writing the stable version is 6.10.2 so the complete inclusion is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script src="//cdn.rawgit.com/dcodeIO/protobuf.js/6.10.2/dist/protobuf.min.js"&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bottom line, just find the latest version of &lt;code&gt;protobuf.min.js&lt;/code&gt; and include it in your page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Listen to the WebSocket
&lt;/h2&gt;

&lt;p&gt;The WebSocket implementation is pretty straightforward, and you can find &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#examples"&gt;more information here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The most important change compared to online tutorials I found, is that you need to specify the binaryType of the socket, as shown below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;socket.binaryType = 'arraybuffer'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apart from this change, the implementation is easy:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You create the WebSocket&lt;/li&gt;
&lt;li&gt;You listen for the connection to open and send the initial message&lt;/li&gt;
&lt;li&gt;You keep listening for incoming messages&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s the full code for the WebSocket part&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// 1. Socket Init
const socket = new WebSocket('wss://remote-service.com/');
socket.binaryType = 'arraybuffer' // Important!

// 2. Listen to Connection opening
socket.addEventListener("open", function (event) {
    console.log("Connection Opened, sending message");
    socket.send('{"message": "HelloWorld!"}');
};

// Listen to Error Events
socket.addEventListener("error", function(err) {
    console.log("error: ", err);
});

// Listen for Connection closure
socket.addEventListener("close", function() {
    console.log("close");
});

// 3. Most Importantly: Listen for received messages
socket.addEventListener('message', function (event) {
     // Protobuf Implementation here, to manage messages
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Protobuf to decode the message
&lt;/h2&gt;

&lt;p&gt;If you try to console.log the message received from the last Listener, you will receive a base64 encoded binary array. &lt;/p&gt;

&lt;p&gt;This is where Protobuf comes in to decode the message and provide the usable message.&lt;/p&gt;

&lt;p&gt;To get started you need to create a &lt;code&gt;.proto&lt;/code&gt; file which contains the instructions on how to interpret the binary array you receive. If, like me, you’re implementing this for a remote service, they will provide the &lt;code&gt;.proto&lt;/code&gt; file, or you can write one yourself based on their specs. The format is pretty straightforward and it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;message MyMessage{
  required string title= 1;
  required int32 id = 2;
  optional string text = 3;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you have the &lt;code&gt;.proto&lt;/code&gt; file, just save it and place it in a path that can be reached by the WebServer. In my example I’ve saved it as &lt;code&gt;/js/mymessage.proto&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now that we have the &lt;code&gt;.proto&lt;/code&gt; file ready, we can use it to decode the message that is coming to us from the WebSocket. Expanding the code at point 3 above, we have something like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;socket.addEventListener('message', function (event) {
  // I retrieve the Base64 Encoded string
  msg = event.data
  // I transform such string to the typed array needed
  buffer = Uint8Array.from(atob(msg), c =&amp;gt; c.charCodeAt(0))

  // Initiate the Protobuf library by opening the .proto file
  protobuf.load("/js/mymessage.proto", function(err, root) {

    // Retrieve the type of message I want to decode from the .proto file
    var MyMessage = root.lookupType("MyMessage");

    // Finally I can decode my message
    var message = MyMessage.decode(buffer);

    // message now contains an object with the properties specified in the .proto file
    console.log(message)   
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The whole thing
&lt;/h2&gt;

&lt;p&gt;Here’s the complete script, which should give you a good idea at how to implement a remove WebSocket using Protobuf in Javascript&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// 1. Socket Init
const socket = new WebSocket('wss://remote-service.com/');
socket.binaryType = 'arraybuffer' // Important!

// 2. Listen to Connection opening
socket.addEventListener("open", function (event) {
    console.log("Connection Opened, sending message");
    socket.send('{"message": "HelloWorld!"}');
};

// Listen to Error Events
socket.addEventListener("error", function(err) {
    console.log("error: ", err);
});

// Listen for Connection closure
socket.addEventListener("close", function() {
    console.log("close");
});

// 3. Most Importantly: Listen for received messages
socket.addEventListener('message', function (event) {
  // I retrieve the Base64 Encoded string
  msg = event.data
  // I transform such string to the typed array needed
  buffer = Uint8Array.from(atob(msg), c =&amp;gt; c.charCodeAt(0))

  // Initiate the Protobuf library by opening the .proto file
  protobuf.load("/js/mymessage.proto", function(err, root) {

    // Retrieve the type of message I want to decode from the .proto file
    var MyMessage = root.lookupType("MyMessage");

    // Finally I can decode my message
    var message = MyMessage.decode(buffer);

    // message now contains an object with the properties specified in the .proto file
    console.log(message)   
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>javascript</category>
      <category>websocket</category>
      <category>protobuf</category>
    </item>
    <item>
      <title>10 Great Homebrew formulas for Web Developers</title>
      <dc:creator>Andrea Olivato</dc:creator>
      <pubDate>Sat, 26 Dec 2020 09:43:38 +0000</pubDate>
      <link>https://dev.to/andreaolivato/10-great-homebrew-formulas-for-web-developers-15dh</link>
      <guid>https://dev.to/andreaolivato/10-great-homebrew-formulas-for-web-developers-15dh</guid>
      <description>&lt;p&gt;&lt;a href="https://brew.sh/"&gt;Homebrew&lt;/a&gt; is the first software I Install on any MAC machine. I think it gives me the feeling to be back on my beloved Linux box, with &lt;a href="https://wiki.debian.org/Apt"&gt;APT&lt;/a&gt; or &lt;a href="https://www.redhat.com/sysadmin/how-manage-packages"&gt;YUM&lt;/a&gt;. It's definitely not the same thing, but you know us nostalgic.&lt;/p&gt;

&lt;p&gt;Nostalgia aside, I wanted to summarise a collection of favourite formulas that I find super useful for my daily tasks, specifically thinking about a daily developer life.&lt;/p&gt;

&lt;h1&gt;
  
  
  *EMP (Nginx, Mysql, PHP) Stack
&lt;/h1&gt;

&lt;p&gt;Homebrew allows a very quick deployment of a *EMP stack, which I prefer compared to a container or virtual environment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install nginx php mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configuration files are located in &lt;code&gt;/usr/local/etc/&lt;/code&gt; and is the same as a Linux box.&lt;/p&gt;

&lt;p&gt;Formulas are updated very quickly: PHP 8.0 was available on homebrew just a few days after the stable release.&lt;/p&gt;

&lt;h1&gt;
  
  
  AWS
&lt;/h1&gt;

&lt;p&gt;Who doesn't need to use AWS on a daily basis to optimise/deploy stuff or simply monitor their infrastructure?&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h1&gt;
  
  
  CURL &amp;amp; WGET
&lt;/h1&gt;

&lt;p&gt;Can't live without them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install curl wget
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  RCLONE
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://rclone.org/"&gt;Rclone&lt;/a&gt; is incredibly useful to quickly transfer files across different cloud services. Personally, I've used to backups S3 buckers to Google Drive or replicate S3 buckets into Azure and it works splendidly.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h1&gt;
  
  
  PHP-CS-FIXER
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/FriendsOfPHP/PHP-CS-Fixer"&gt;Php-cs-Fixer&lt;/a&gt; is a great command-line utility to enforce coding standards. Easily integrated into deploy flows or simply in your favourite editor, in my case Sublime.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install php-cs-fixer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another alternative I tested and liked is &lt;a href="https://github.com/squizlabs/PHP_CodeSniffer/wiki/Fixing-Errors-Automatically"&gt;phpcbf&lt;/a&gt; which you can install via composer&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer global require squizlabs/php_codesniffer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  STRIPE
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://stripe.com/"&gt;Stripe&lt;/a&gt; CLI is incredibly useful for monitoring of activities, frauds, and automated tests/reporting. The Webhook listener is also very handy.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h1&gt;
  
  
  HTOP
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://htop.dev/"&gt;HTOP&lt;/a&gt; is a great improvement of top, which I use everywhere, from DEV servers to my own laptop. I know it's not as modern as &lt;a href="https://github.com/cjbassi/ytop"&gt;YTOP&lt;/a&gt; but I got used to it and can't get to change.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



</description>
      <category>homebrew</category>
      <category>mac</category>
      <category>php</category>
      <category>brew</category>
    </item>
    <item>
      <title>Install PHP 8 on AWS 
Amazon Linux 2</title>
      <dc:creator>Andrea Olivato</dc:creator>
      <pubDate>Mon, 07 Dec 2020 02:54:39 +0000</pubDate>
      <link>https://dev.to/andreaolivato/install-php-8-on-aws-amazon-linux-2-2mdl</link>
      <guid>https://dev.to/andreaolivato/install-php-8-on-aws-amazon-linux-2-2mdl</guid>
      <description>&lt;p&gt;PHP 8 is finally here, and it's time to upgrade our DEV environments to start resolving all those Warnings :)&lt;/p&gt;

&lt;p&gt;At Lnk.Bio we use the official &lt;a href="https://aws.amazon.com/amazon-linux-2/"&gt;AWS Amazon Linux 2 AMI&lt;/a&gt;, and usually rely on the library &lt;strong&gt;Amazon Linux Extras&lt;/strong&gt; to update/switch php version, but PHP 8 is yet to be included (and I couldn't find any timeline anywhere).&lt;/p&gt;

&lt;p&gt;Therefore, I found the best way to install PHP 8 is to rely on &lt;a href="https://rpms.remirepo.net/"&gt;Remi's RPM repository&lt;/a&gt; which features all major PHP versions for RHEL/Centos (on which Amazon Linux 2 AMI is sort of based). &lt;/p&gt;

&lt;p&gt;The steps are quite easy:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Remove current PHP versions&lt;/li&gt;
&lt;li&gt;Add Remi's RPM repo for Centos 7&lt;/li&gt;
&lt;li&gt;Install PHP 8&lt;/li&gt;
&lt;li&gt;Install PHP 8 additional libraries&lt;/li&gt;
&lt;li&gt;Paths/Configuration Notes&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Please note that this guide is not intended for those who want to run multiple PHP versions at the same time. It will replace the current PHP version with PHP 8.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's go&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Remove current PHP version
&lt;/h2&gt;

&lt;p&gt;If you don't have a formal documentation (you should!) of which additional PHP packages you need for your app, you can get a list by running.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo yum list installed | grep php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you're confident you can reinstall everything, start by removing old PHP packages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo yum remove php*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Add Remi's RPM repo for Centos 7
&lt;/h2&gt;

&lt;p&gt;You will also need EPEL for Centos 7 for dependencies. I guess most people have this already enabled on Amazon Linux 2 AMI, but I am adding it anyway for clarity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
sudo yum install https://rpms.remirepo.net/enterprise/remi-release-7.rpm
sudo yum-config-manager --enable remi-php80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Install PHP 8
&lt;/h2&gt;

&lt;p&gt;Now this is quite easy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo yum install php80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify PHP is installed correctly by running&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php80 -v
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Install PHP 8 Additional libraries
&lt;/h2&gt;

&lt;p&gt;If you use additional modules/libraries, you can now install them. Naming convention remained the same, but they have the prefix php80-php-{library}&lt;/p&gt;

&lt;p&gt;For example, if you use php-fpm you'll run &lt;code&gt;sudo yum install php80-php-fpm&lt;/code&gt;; if you need mysqlnd you'll run &lt;code&gt;sudo yum install php80-php-mysqlnd&lt;/code&gt; etc...&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Paths/Configuration notes
&lt;/h2&gt;

&lt;p&gt;Please note that Remi's PHP will be installed under /opt and the binary is &lt;code&gt;php80&lt;/code&gt;. Here are a few locations you need to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PHP configuration files (php.ini, php-fpm.d etc..): /etc/opt/remi/php80/&lt;/li&gt;
&lt;li&gt;PHP logs: /var/opt/remi/php80/log/&lt;/li&gt;
&lt;li&gt;PHP Binary: /usr/bin/php80&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can of course create symlinks if you prefer.&lt;/p&gt;

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