<?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: Andrew Davis</title>
    <description>The latest articles on DEV Community by Andrew Davis (@restoreddev).</description>
    <link>https://dev.to/restoreddev</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%2F35048%2F42f91f60-69b2-4cad-b235-cf212d9c45b0.jpg</url>
      <title>DEV Community: Andrew Davis</title>
      <link>https://dev.to/restoreddev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/restoreddev"/>
    <language>en</language>
    <item>
      <title>What is an HMAC?</title>
      <dc:creator>Andrew Davis</dc:creator>
      <pubDate>Fri, 17 Jan 2020 13:40:00 +0000</pubDate>
      <link>https://dev.to/restoreddev/what-is-an-hmac-2f09</link>
      <guid>https://dev.to/restoreddev/what-is-an-hmac-2f09</guid>
      <description>&lt;p&gt;I recently was asked to explain some code that used an HMAC signature for authenticating/verifying a message. While I understood that HMACs are used for message authenticity, I did not fully grasp the implementation. Here is the information I have discovered through more research.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Message_authentication_code"&gt;MAC&lt;/a&gt; stands for "message authentication code". Essentially, it is a way to generate a code to be submitted with a message that verifies the sender of the message and also verifies the message has not been modified. &lt;a href="https://en.wikipedia.org/wiki/HMAC"&gt;HMAC&lt;/a&gt; stands for "hash-based message authentication code". It uses a cryptographic hashing algorithm to generate the MAC. An HMAC algorithm works by hashing a message along with a secret key. The resulting hash is called a signature or digest. The message is then transferred to a recipient along with the signature. If the recipient has the secret key, they can hash the message with the same algorithm and verify the resulting signature matches the one sent with the message. As a result, the message is simultaneously authenticated and its integrity verified.&lt;/p&gt;

&lt;p&gt;We can try to better understand an HMAC through an example. Let us imagine that you have a doctor's office application that needs to send an HTTP request to a secure API that contains medical history for patients. The message you want to send to the API is a JSON packet containing the results of the latest visit to the doctor by the patient.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"first_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Andrew"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"last_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Davis"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"visit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2020-01-12 09:56:12"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"symptoms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"sore throat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"runny nose"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"sneezing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"headache"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"diagnosis"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Common Cold"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"suggested_treatment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"drink water"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"rest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"consume ibuprofen twice a day"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The API has provided you with a secret key that might look something like this &lt;code&gt;13441c78e4440683a9e32aa7e4ee39fd3544b87968cc5a30f621f7e32029b2f5&lt;/code&gt; and says you must use it to create a SHA-256 HMAC signature to pass along in the &lt;code&gt;Authorization&lt;/code&gt; HTTP header for requests.&lt;/p&gt;

&lt;p&gt;Our programming language of choice is PHP. Thankfully, PHP already has functions for generating HMAC signatures. To see all the supported algorithms, you can run &lt;code&gt;hash_hmac_algos()&lt;/code&gt; and PHP will return an array of all the hash types supported. Here is the list for PHP 7.4 on my machine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; hash_hmac_algos&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;              
  &lt;span class="s2"&gt;"md2"&lt;/span&gt;,       
  &lt;span class="s2"&gt;"md4"&lt;/span&gt;,       
  &lt;span class="s2"&gt;"md5"&lt;/span&gt;,       
  &lt;span class="s2"&gt;"sha1"&lt;/span&gt;,      
  &lt;span class="s2"&gt;"sha224"&lt;/span&gt;,    
  &lt;span class="s2"&gt;"sha256"&lt;/span&gt;,    
  &lt;span class="s2"&gt;"sha384"&lt;/span&gt;,    
  &lt;span class="s2"&gt;"sha512/224"&lt;/span&gt;,
  &lt;span class="s2"&gt;"sha512/256"&lt;/span&gt;,
  &lt;span class="s2"&gt;"sha512"&lt;/span&gt;,    
  &lt;span class="s2"&gt;"sha3-224"&lt;/span&gt;,  
  &lt;span class="s2"&gt;"sha3-256"&lt;/span&gt;,  
  &lt;span class="s2"&gt;"sha3-384"&lt;/span&gt;,  
  &lt;span class="s2"&gt;"sha3-512"&lt;/span&gt;,  
  &lt;span class="s2"&gt;"ripemd128"&lt;/span&gt;, 
  &lt;span class="s2"&gt;"ripemd160"&lt;/span&gt;, 
  &lt;span class="s2"&gt;"ripemd256"&lt;/span&gt;, 
  &lt;span class="s2"&gt;"ripemd320"&lt;/span&gt;, 
  &lt;span class="s2"&gt;"whirlpool"&lt;/span&gt;, 
  &lt;span class="s2"&gt;"tiger128,3"&lt;/span&gt;,
  &lt;span class="s2"&gt;"tiger160,3"&lt;/span&gt;,
  &lt;span class="s2"&gt;"tiger192,3"&lt;/span&gt;,
  &lt;span class="s2"&gt;"tiger128,4"&lt;/span&gt;,
  &lt;span class="s2"&gt;"tiger160,4"&lt;/span&gt;,
  &lt;span class="s2"&gt;"tiger192,4"&lt;/span&gt;,
  &lt;span class="s2"&gt;"snefru"&lt;/span&gt;,    
  &lt;span class="s2"&gt;"snefru256"&lt;/span&gt;, 
  &lt;span class="s2"&gt;"gost"&lt;/span&gt;,      
  &lt;span class="s2"&gt;"gost-crypto"&lt;/span&gt;
  &lt;span class="s2"&gt;"haval128,3"&lt;/span&gt;,
  &lt;span class="s2"&gt;"haval160,3"&lt;/span&gt;,
  &lt;span class="s2"&gt;"haval192,3"&lt;/span&gt;,
  &lt;span class="s2"&gt;"haval224,3"&lt;/span&gt;,
  &lt;span class="s2"&gt;"haval256,3"&lt;/span&gt;,
  &lt;span class="s2"&gt;"haval128,4"&lt;/span&gt;,
  &lt;span class="s2"&gt;"haval160,4"&lt;/span&gt;,
  &lt;span class="s2"&gt;"haval192,4"&lt;/span&gt;,
  &lt;span class="s2"&gt;"haval224,4"&lt;/span&gt;,
  &lt;span class="s2"&gt;"haval256,4"&lt;/span&gt;,
  &lt;span class="s2"&gt;"haval128,5"&lt;/span&gt;,
  &lt;span class="s2"&gt;"haval160,5"&lt;/span&gt;,
  &lt;span class="s2"&gt;"haval192,5"&lt;/span&gt;,
  &lt;span class="s2"&gt;"haval224,5"&lt;/span&gt;,
  &lt;span class="s2"&gt;"haval256,5"&lt;/span&gt;,
&lt;span class="o"&gt;]&lt;/span&gt;              
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We see that SHA-256 is supported by PHP. &lt;a href="https://en.wikipedia.org/wiki/SHA-2"&gt;SHA-256&lt;/a&gt; is a common hashing algorithm created by the Unites States' NSA which is often used with HMAC algorithms.&lt;/p&gt;

&lt;p&gt;Now, we need to create the actual HMAC signature of our message. To do so, we can use PHP's &lt;a href="https://www.php.net/manual/en/function.hash-hmac.php"&gt;&lt;code&gt;hash_hmac&lt;/code&gt;&lt;/a&gt; function. The first parameter is the algorithm, the second parameter is the message and the third parameter is the secret key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; hash_hmac&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'sha256'&lt;/span&gt;,&lt;span class="se"&gt;\&lt;/span&gt;
... &lt;span class="s1"&gt;'{"first_name": "Andrew","last_name": "Davis","visit": "2020-01-12 09:56:12","symptoms": ["sore throat","runny nose","sneezing","headache"],"diagnosis": "Common Cold","suggested_treatment": ["drink water","rest","consume ibuprofen twice a day"]}'&lt;/span&gt;,&lt;span class="se"&gt;\&lt;/span&gt;
... &lt;span class="s1"&gt;'13441c78e4440683a9e32aa7e4ee39fd3544b87968cc5a30f621f7e32029b2f5'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"0def47f4878406abf864da0d34f9e3627653317e7c77da8230e0f65b52c09479"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;PHP responds with a message digest/signature: &lt;code&gt;0def47f4878406abf864da0d34f9e3627653317e7c77da8230e0f65b52c09479&lt;/code&gt;. We can submit the JSON message to the API along with the signature. The API will then take the message and it will create an HMAC signature using SHA-256 and its secret key. If its resulting HMAC signature matches the HMAC you provided, then it accepts the message for processing.&lt;/p&gt;

&lt;p&gt;The API exchange highlights the two main benefits of HMAC.&lt;/p&gt;

&lt;p&gt;First, since an HMAC requires a secret key, both the sender and recipient have to have the same secret key for HMAC verification to work. As a result, the HMAC acts similarly to a password. It is very important to keep the secret key safe. Since it is used like a password, it needs to be saved in encrypted storage. It is also important to use a sufficiently long secret key that cannot be brute forced by password breakers.&lt;/p&gt;

&lt;p&gt;Second, an HMAC is based not only on the secret key, but also on the message itself. If two HMACs are created with the same secret key, but different messages, the resulting codes will be different. When the API sees that its HMAC matches the HMAC in the request, it knows the request was not modified during transport. Since hackers will try to modify messages in between clients and servers, HMAC signatures can be a powerful tool to verify authenticity of requests.&lt;/p&gt;

&lt;p&gt;Hopefully this explanation has shed some light on HMAC signatures. Unfortunately, I do not have the math and cryptography experience to explain how the HMAC algorithm works to create the signature. Maybe someone else in the DEV Community can provide a layman's explanation of the computation.&lt;/p&gt;

&lt;p&gt;What is your experience with HMAC and where have you seen it used it effectively?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>php</category>
    </item>
    <item>
      <title>Let's Talk Windows vs macOS</title>
      <dc:creator>Andrew Davis</dc:creator>
      <pubDate>Fri, 27 Dec 2019 14:38:55 +0000</pubDate>
      <link>https://dev.to/restoreddev/let-s-talk-windows-vs-macos-5799</link>
      <guid>https://dev.to/restoreddev/let-s-talk-windows-vs-macos-5799</guid>
      <description>&lt;p&gt;When I started writing websites professionally, my work computer ran Windows so I had to learn to set up PHP and Laravel using IIS (an unpleasant experience). However, my personal computer was a 2015 MacBook Pro and I really liked the Bash terminal, Homebrew and &lt;a href="https://laravel.com/docs/6.x/valet" rel="noopener noreferrer"&gt;Valet&lt;/a&gt;. When I moved to my current employer, I had the option to have an HP laptop or a MacBook so I naturally chose the MacBook. I became a full Apple convert. It was really easy to work on web development because macOS is so similar to Linux. Homebrew makes package installation really easy. PHP runs really well on macOS because of the Unix environment. I was ready to ride in the sunset as a satisfied Apple customer.&lt;/p&gt;

&lt;p&gt;Well guess what? I am writing this blog post on Windows right now.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fdizc6cstpzh9a4vsig8g.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fdizc6cstpzh9a4vsig8g.jpg" alt="Shocked Animals"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You do not hear many stories about users going back to Windows after switching to Mac. So what happened?&lt;/p&gt;

&lt;p&gt;Well first off, I am not a total Microsoft convert. I still use a MacBook for work and am generally happy with it. I recently got an upgrade to a 2019 MacBook from my employer and it works well. I want my escape key back (my pinky shudders on the cold Touch Bar every time I exit Vim), but overall it is a solid laptop.&lt;/p&gt;

&lt;p&gt;At home, my personal computer is a custom assembled PC running Windows. This year my 2015 MacBook started showing its age. I also was running out of space on the hard drive. 256GB does not go very far these days. I found that I was not using the laptop part of my MacBook very much. Generally, I just used it on a desk and it never left the house. When I looked at the prices of a new Mac, an equivalent replacement to what I had would have cost me $2400 (USD) which was not worth it to me because I use my personal computer mainly for blogging, streaming and small side projects. So it was then that I decided to try my hand at building a PC. I ended up with a desktop PC that has better specs than a 15" MacBook and only cost me $1300.&lt;/p&gt;

&lt;p&gt;My custom PC has a six core Ryzen 5 processor with 16GB of RAM and a Nvidia RTX video card running off of two SSDs. It is very fast, apps load immediately and basic things like web browsing feel incredibly snappy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fdotvozbgm1d8dplbdu4c.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fdotvozbgm1d8dplbdu4c.jpg" alt="Fast Motorcycle"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also love that I can upgrade the hardware on my PC whenever I want. Do I want to upgrade to 32GB of RAM? Easy. Add another hard drive? Piece of cake. MacBooks will never offer this level of customization.&lt;/p&gt;

&lt;p&gt;Unfortunately, there are always downsides. The number one for me is the Windows filesystem. I really miss using a POSIX operating system. Microsoft is working on it with the &lt;a href="https://docs.microsoft.com/en-us/windows/wsl/install-win10" rel="noopener noreferrer"&gt;Windows Subsystem for Linux&lt;/a&gt; which I have been using some. I have run into a lot of bugs with it though and Microsoft is having to rewrite it for WSL 2 which supposedly will offer more stability. I am hopeful that WSL 2 will solve my complaints. We will see when it comes out of beta in 2020.&lt;/p&gt;

&lt;p&gt;I also am struggling to find equivalent apps on Windows for what I use on Mac. There is no Alfred or iTerm or Sequel Pro on Windows. While I have found some alternative options on Windows, they are not quite as good as the Mac apps.&lt;/p&gt;

&lt;p&gt;If you asked me if you should get a Mac or PC, I would say:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fu4scyeok4121f3ycmgs5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fu4scyeok4121f3ycmgs5.jpg" alt="Confused and Stressed Computer User"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On a PC, you can have faster hardware that can be upgraded for much cheaper than a Mac. However, web development is still easier on a Mac because of the Unix underbelly and app ecosystem. I am crossing my fingers that Windows will improve with projects like WSL 2 and the new &lt;a href="https://github.com/microsoft/terminal" rel="noopener noreferrer"&gt;Windows Terminal&lt;/a&gt;, but only time will tell if they become as good as what Macs offer.&lt;/p&gt;

&lt;p&gt;Ultimately, I am happy with my PC right now. I like to play video games so that is another plus in the PC column. If I was having to use it full time for PHP development though, I doubt I would be as productive as I am on a Mac. &lt;/p&gt;

&lt;p&gt;What do you like to use for web development? Have you recently switched to Windows from a Mac? What are your favorite apps?&lt;/p&gt;

&lt;p&gt;P.S. I have tried to use a full Linux distro (Ubuntu), but had basic issues with it like audio not working, so left it out of the comparison. I may attempt to use a Linux distro again in the future.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Introduction to PHP 7.4 Preload</title>
      <dc:creator>Andrew Davis</dc:creator>
      <pubDate>Sat, 10 Aug 2019 18:16:02 +0000</pubDate>
      <link>https://dev.to/restoreddev/introduction-to-php-7-4-preload-4lg4</link>
      <guid>https://dev.to/restoreddev/introduction-to-php-7-4-preload-4lg4</guid>
      <description>&lt;p&gt;PHP 7.4 is the latest version of the PHP programming language that will launch later this year. PHP 7.4 recently went into beta, so I started exploring the new features. One feature showing a lot of promise is called &lt;a href="https://wiki.php.net/rfc/preload"&gt;Opcache Preload&lt;/a&gt;. Using preload you can set PHP to load certain PHP files into memory on startup. Doing so reduces the amount of files PHP has to compile when receiving an HTTP request which improves performance. Before exploring preload, let us look at how opcache works in the PHP runtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Opcache Is Your Friend
&lt;/h2&gt;

&lt;p&gt;In PHP, the term PHP is used for the programming language. However, the runtime that executes PHP code is called the Zend Engine. When the Zend Engine receives a request for a PHP file, it actually compiles the PHP file into a list of operation codes, hence the term &lt;code&gt;opcode&lt;/code&gt;. The &lt;code&gt;opcache&lt;/code&gt; Zend Engine extension stores those opcodes in memory after a PHP file is compiled, so that the PHP file does not have to be compiled again in subsequent requests for the file.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;opcache.preload&lt;/code&gt; directive allows a PHP programmer to instruct the opcache to cache the opcodes for a set of PHP files when the Zend Engine is activated. The preload option should be pointed to a PHP file that runs the function &lt;a href="https://www.php.net/manual/en/function.opcache-compile-file.php"&gt;&lt;code&gt;opcache_compile_file&lt;/code&gt;&lt;/a&gt; on the files you want preloaded.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enabling Preload
&lt;/h2&gt;

&lt;p&gt;To test preloading, I set up an &lt;a href="https://github.com/restoreddev/preloading-example"&gt;example project&lt;/a&gt; that uses &lt;a href="http://www.slimframework.com/docs/v3/"&gt;Slim 3&lt;/a&gt; for routing.&lt;/p&gt;

&lt;p&gt;To use preloading, you have to install PHP 7.4. I am using Ubuntu WSL on Windows with the &lt;a href="https://launchpad.net/~ondrej/+archive/ubuntu/php"&gt;ondrej/php&lt;/a&gt; PPA activated. Since I'm using Ondrej's PPA, I can run &lt;code&gt;sudo apt install php7.4-fpm&lt;/code&gt; in bash to get the latest 7.4 beta on my system. I use the FPM installation with Nginx as my web server and a host entry called &lt;code&gt;preloading.local&lt;/code&gt; pointed at my project. After installation, I opened the FPM php.ini file (located at &lt;code&gt;/etc/php/7.4/fpm/php.ini&lt;/code&gt; on my system) and changed the &lt;code&gt;opcache.preload&lt;/code&gt; option to the path to my &lt;code&gt;preload.php&lt;/code&gt; file in my project.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;preload.php&lt;/code&gt; file uses a modified &lt;code&gt;preload&lt;/code&gt; function based on Dmitry Stogov's example in the &lt;a href="https://wiki.php.net/rfc/preload"&gt;Preload RFC&lt;/a&gt;. I have all the Slim dependencies loaded in a &lt;code&gt;vendor&lt;/code&gt; folder using Composer. I then use the &lt;code&gt;preload&lt;/code&gt; function in my &lt;code&gt;preload.php&lt;/code&gt; on all the Composer source files I need to run the Slim application. After restarting PHP FPM (&lt;code&gt;sudo service php7.4-fpm restart&lt;/code&gt;), I can open &lt;code&gt;preloading.local&lt;/code&gt; in my browser and see my application run successfully.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Thoughts on Preload
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;I like that I did not have to use the Composer autoloader for my framework. Since all of the framework code was preloaded, autoloading is unnecessary. I do hope that Composer will generate an automatic &lt;code&gt;preload.php&lt;/code&gt; file, like the &lt;code&gt;autoload.php&lt;/code&gt; file, so that vendor dependencies can be preloaded easily.&lt;/li&gt;
&lt;li&gt;The performance gain is miniscule for a small project like this one, however, I can see preloading being a great way to speed up large frameworks like Symfony, Laravel and especially Magento.&lt;/li&gt;
&lt;li&gt;Preloading will be tricky to implement if you have multiple PHP projects on the same server, since you can only set one file to be preloaded.&lt;/li&gt;
&lt;li&gt;I had an issue where preloading would not load the &lt;code&gt;functions.php&lt;/code&gt; file in the &lt;code&gt;nikic/fast-route&lt;/code&gt; module because it was wrapped in an &lt;code&gt;if&lt;/code&gt; statement. I had to set up a patch file to manually load those functions without the &lt;code&gt;if&lt;/code&gt; statement. It is probably because 7.4 is still in beta or my &lt;code&gt;preload.php&lt;/code&gt; needs to be improved.&lt;/li&gt;
&lt;li&gt;I do not think many PHP developers will use preload in development environments. I generally am reluctant to use features in production that are unused in dev because of the potential for unseen issues to arise on production servers. However, the risk is pretty low for preloading, so it will still be worth it to have it enabled.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All in all, I'm really looking forward to the performance gains from preloading. PHP is already one of the fastest scripting languages on the web and I am happy that the core team continues to push PHP into faster territories.&lt;/p&gt;

&lt;p&gt;Next, I want to try &lt;a href="https://wiki.php.net/rfc/arrow_functions_v2"&gt;arrow functions&lt;/a&gt;, the &lt;a href="https://wiki.php.net/rfc/ffi"&gt;foreign function interface&lt;/a&gt; and &lt;a href="https://wiki.php.net/rfc/typed_properties_v2"&gt;typed properties&lt;/a&gt;. There are a lot of great features being added to PHP soon!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>php</category>
      <category>preload</category>
      <category>opcache</category>
    </item>
    <item>
      <title>How to Write a Magento 2 Console Command</title>
      <dc:creator>Andrew Davis</dc:creator>
      <pubDate>Sun, 09 Jun 2019 20:54:32 +0000</pubDate>
      <link>https://dev.to/restoreddev/how-to-write-a-magento-2-console-command-1gl8</link>
      <guid>https://dev.to/restoreddev/how-to-write-a-magento-2-console-command-1gl8</guid>
      <description>&lt;p&gt;In Magento 2, the platform introduced a new command line interface called &lt;code&gt;bin/magento&lt;/code&gt; that is included in every installation. Most Magento developers are familiar with it because it makes it very easy to peform common tasks on the install like clear cache and install a database. What you might not know is that you can add custom commands to the Magento CLI to allow you to run your own code. I have used this feature to create custom cron jobs that can be executed by the OS cron instead of Magento's cron system. Magento's CLI is based on the &lt;a href="https://symfony.com/doc/current/components/console.html"&gt;Symfony Console&lt;/a&gt; package which is commonly used in the PHP ecosystem. Laravel bases their &lt;code&gt;artisan&lt;/code&gt; command on Symfony Console, for example. In Magento 2, you can create custom Symfony Console commands and include them in Magento's CLI. To help other developers get started with console commands, I want to provide this quick tutorial.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I am assuming you have a Magento 2 installation ready to use for development. To learn how to set up Magento, check out &lt;a href="https://devdocs.magento.com/guides/v2.3/install-gde/bk-install-guide.html"&gt;Magento's devdocs post&lt;/a&gt; for installation instructions. I used Magento Community 2.3.1 for this tutorial.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Make a Module
&lt;/h3&gt;

&lt;p&gt;We need to create our own custom module in &lt;code&gt;app/code&lt;/code&gt;. I am calling my module &lt;code&gt;Restoreddev_Console&lt;/code&gt;. For every module we need a &lt;code&gt;registration.php&lt;/code&gt; and &lt;code&gt;module.xml&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;app/code/Restoreddev/Console/registration.php&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="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="nx"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;\Magento\Framework\Component\ComponentRegistrar&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;ComponentRegistrar&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ComponentRegistrar&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;MODULE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Restoreddev_Console'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;__DIR__&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;app/code/Restoreddev/Console/etc/module.xml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;config&lt;/span&gt; &lt;span class="na"&gt;xmlns:xsi=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt; &lt;span class="na"&gt;xsi:noNamespaceSchemaLocation=&lt;/span&gt;&lt;span class="s"&gt;"urn:magento:framework:Module/etc/module.xsd"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;module&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Restoreddev_Console"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/config&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now you can run &lt;code&gt;php bin/magento setup:upgrade&lt;/code&gt; to install your custom module into Magento's database.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Create Console Command Class
&lt;/h3&gt;

&lt;p&gt;Next, we can create a class that implements Symfony Command that will be run when our command is executed. I want to create a custom command that clears the &lt;code&gt;generated&lt;/code&gt; directory, similar to how &lt;code&gt;cache:flush&lt;/code&gt; works. Add this class to your module:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;app/code/Restoreddev/Console/Console/Command/GeneratedFlushCommand.php&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Restoreddev\Console\Console\Command&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Symfony\Component\Console\Command\Command&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Magento\Framework\Filesystem\DirectoryList&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Magento\Framework\Filesystem\Io\File&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;FileIo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Symfony\Component\Console\Input\InputInterface&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Symfony\Component\Console\Output\OutputInterface&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GeneratedFlushCommand&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Command&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$fileIo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$directoryList&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;FileIo&lt;/span&gt; &lt;span class="nv"&gt;$fileIo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;DirectoryList&lt;/span&gt; &lt;span class="nv"&gt;$directoryList&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;fileIo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$fileIo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;directoryList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$directoryList&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'generated:flush'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;setDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Deletes code in generated folder'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;InputInterface&lt;/span&gt; &lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OutputInterface&lt;/span&gt; &lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$path&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="na"&gt;directoryList&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'generated'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$dirs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="s2"&gt;/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;GLOB_ONLYDIR&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;$dirs&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;fileIo&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;rmdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$recursive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;writeln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Generated folder successfully flushed'&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;There is a lot happening in this class, so we need to analyze it in sections.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You will see that the class extends &lt;code&gt;Symfony\Component\Console\Command\Command&lt;/code&gt;. The Symfony parent class provides the interface for our class to be included in the command list.&lt;/li&gt;
&lt;li&gt;In the &lt;code&gt;__construct&lt;/code&gt; method, we can inject Magento dependencies like other Magento classes. However, you do have to run &lt;code&gt;parent::__construct();&lt;/code&gt; for the class to be implemented properly.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;configure&lt;/code&gt; method allows you to define the command name and description that appears in the CLI menu.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;execute&lt;/code&gt; method contains the code that will run when the CLI command is executed. The method receives two objects: &lt;code&gt;$input&lt;/code&gt; (contains any console arguments) and &lt;code&gt;$output&lt;/code&gt; (allows you to send text to the terminal). I am using Magento's classes to get the &lt;code&gt;generated&lt;/code&gt; directory and to delete any directories inside of it. At the end, I am using &lt;code&gt;$output-&amp;gt;writeln()&lt;/code&gt; to send a success message to the user.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  3. Register Command in Magento
&lt;/h3&gt;

&lt;p&gt;Finally, we need to register the command in Magento's dependency injection system. Create the following &lt;code&gt;di.xml&lt;/code&gt; file in your module.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;app/code/Restoreddev/Console/etc/di.xml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;config&lt;/span&gt; &lt;span class="na"&gt;xmlns:xsi=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt; &lt;span class="na"&gt;xsi:noNamespaceSchemaLocation=&lt;/span&gt;&lt;span class="s"&gt;"urn:magento:framework:ObjectManager/etc/config.xsd"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;type&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Magento\Framework\Console\CommandListInterface"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;arguments&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;argument&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"commands"&lt;/span&gt; &lt;span class="na"&gt;xsi:type=&lt;/span&gt;&lt;span class="s"&gt;"array"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"generatedFlushCommand"&lt;/span&gt; &lt;span class="na"&gt;xsi:type=&lt;/span&gt;&lt;span class="s"&gt;"object"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Restoreddev\Console\Console\Command\GeneratedFlushCommand&lt;span class="nt"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/argument&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/arguments&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/type&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/config&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;di.xml&lt;/code&gt;, we are targeting the &lt;code&gt;CommandListInterface&lt;/code&gt; and adding an additional command to its arguments. Now you can flush Magento's cache (&lt;code&gt;php bin/magento cache:flush&lt;/code&gt;) and run &lt;code&gt;php bin/magento&lt;/code&gt;. You will see a new command called &lt;code&gt;generated:flush&lt;/code&gt;. If you execute it &lt;code&gt;php bin/magento generated:flush&lt;/code&gt;, then you will see all subdirectories in the &lt;code&gt;generated&lt;/code&gt; folder have been deleted.&lt;/p&gt;

&lt;p&gt;I hope this quick tutorial has helped you learn about a neat new feature in Magento 2. If you would like to see another specific Magento tutorial, let me know in the comments!&lt;/p&gt;

</description>
      <category>magento</category>
      <category>php</category>
      <category>webdev</category>
    </item>
    <item>
      <title>GraphQL Server Primer</title>
      <dc:creator>Andrew Davis</dc:creator>
      <pubDate>Mon, 25 Mar 2019 12:59:17 +0000</pubDate>
      <link>https://dev.to/restoreddev/graphql-server-primer-4ekd</link>
      <guid>https://dev.to/restoreddev/graphql-server-primer-4ekd</guid>
      <description>&lt;p&gt;GraphQL is one of the hottest topics in web development right now. I do a lot of work with Magento and they recently announced a whole new GraphQL API to be used for front end development. To learn GraphQL, &lt;a href="https://andrewdavis.me/post/creating-a-magento-theme-with-nextjs-and-graphql/"&gt;I built an experimental Magento frontend using Next.js&lt;/a&gt;. After that project, I still did not understand how to build a GraphQL server. As a result, I decided to build an example GraphQL server using Node.js. The original GraphQL specification was written in JavaScript so it is a good language to use when learning GraphQL. I created a GitHub repository called &lt;a href="https://github.com/restoreddev/graphql-nodejs-example/"&gt;graphql-nodejs-example&lt;/a&gt; if you want to view the whole project. In this post, I want to discuss a few concepts about GraphQL that really helped me understand how it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  A GraphQL Server Has Only One Endpoint
&lt;/h2&gt;

&lt;p&gt;In REST APIs, it is common to have multiple URLs for a single resource. You might have several endpoints for loading and creating data like &lt;code&gt;/tasks&lt;/code&gt;, &lt;code&gt;tasks/1&lt;/code&gt;, &lt;code&gt;/tasks/create&lt;/code&gt;. In GraphQL, your server runs only a single endpoint, usually at the root &lt;code&gt;/&lt;/code&gt; or at &lt;code&gt;/graphql&lt;/code&gt;. When submitting a query to a GraphQL server, you explicitly set the resource you want in the request body, so the server can decide what values to return.&lt;/p&gt;

&lt;h2&gt;
  
  
  GraphQL Is About Types
&lt;/h2&gt;

&lt;p&gt;In a GraphQL API, you define what resources you have using a type language. GraphQL supports &lt;a href="https://graphql.org/learn/schema/#scalar-types"&gt;five scalar types&lt;/a&gt; that you can use to compose more complex object types. The five scalar types are: &lt;code&gt;Int&lt;/code&gt;, &lt;code&gt;Float&lt;/code&gt;, &lt;code&gt;String&lt;/code&gt;, &lt;code&gt;Boolean&lt;/code&gt; and &lt;code&gt;ID&lt;/code&gt;. To create a resource, you build an object type for it. I wanted to emulate a forum so I created three resources: &lt;code&gt;User&lt;/code&gt;, &lt;code&gt;Thread&lt;/code&gt; and &lt;code&gt;Comment&lt;/code&gt;. In GraphQL types, those resources look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Thread&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Comment&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Comment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can see that you can create an object type using the &lt;code&gt;type&lt;/code&gt; keyword followed by a name. In curly braces, you define the properties of the object by writing the name of the property followed by a colon and the type. An exclamation point &lt;code&gt;!&lt;/code&gt; after the property indicates that the value cannot be null.&lt;/p&gt;

&lt;p&gt;You can also use custom types in other custom types. The &lt;code&gt;Thread&lt;/code&gt; type has a user and comments property that reference the other two types I created. Brackets around the type name like &lt;code&gt;[Comment]&lt;/code&gt; indicate that the property is an array.&lt;/p&gt;

&lt;p&gt;When writing a server, where do you put those types? I put them all in a file called &lt;code&gt;schema.graphql&lt;/code&gt; and used the Apollo Server helper &lt;code&gt;gql&lt;/code&gt; to import that file into my server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requests Are Handled By a Query and Mutation Type
&lt;/h2&gt;

&lt;p&gt;In GraphQL, there are two types of requests you can send to a GraphQL server: &lt;code&gt;query&lt;/code&gt; and &lt;code&gt;mutation&lt;/code&gt;. A &lt;code&gt;query&lt;/code&gt; is used to retrieve data and a &lt;code&gt;mutation&lt;/code&gt; is used to perform actions on data, like creating or updating. In your server schema, you define a query object type and a mutation object type, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Thread&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;createThread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Thread&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;createComment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;!,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;threadId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;!,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Comment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can see in my &lt;code&gt;Query&lt;/code&gt; type, I define two ways to retrieve a thread. The &lt;code&gt;threads&lt;/code&gt; property returns an array of all threads and the &lt;code&gt;thread(id: ID!)&lt;/code&gt; returns a single thread. The parentheses denote arguments that can be passed in the query. Since I marked &lt;code&gt;id&lt;/code&gt; as a non-nullable &lt;code&gt;Int&lt;/code&gt;, to retrieve a single thread you have to pass in the &lt;code&gt;id&lt;/code&gt; of a thread in your GraphQL request.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;Mutation&lt;/code&gt; type, there are two properties for creating a thread and creating a comment. Each operation requires a set of values for creating the resource and each returns the newly created resource.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resolving Your Queries and Mutations
&lt;/h2&gt;

&lt;p&gt;After defining the schema, how do you implement the logic to load the resources from a data source? You use resolvers! Resolvers are similar to controllers in a REST API. For each &lt;code&gt;Query&lt;/code&gt; and &lt;code&gt;Mutation&lt;/code&gt; property, you create a JavaScript function that accepts arguments and performs the operation on the resource to load data or change it.&lt;/p&gt;

&lt;p&gt;I used the &lt;a href="https://www.apollographql.com/docs/apollo-server/"&gt;Apollo Server&lt;/a&gt; library to build my GraphQL API. The library allows you to write your schema, import it and pass in a resolver object that will handle all of the requests.&lt;/p&gt;

&lt;p&gt;My Apollo Server setup looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ApolloServer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;apollo-server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/schema.graphql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;typeDefs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resolvers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./resolvers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ApolloServer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;typeDefs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resolvers&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server ready at &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;All I need for my Apollo Server instance is to pass in my schema and resolvers and it will start a node server that I can query.&lt;/p&gt;

&lt;p&gt;My resolvers file just exports a JavaScript object with a Query and Mutation property that holds references to functions for each property defined in my schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;threads&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./threads&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;comments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./comments&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;Mutation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;createThread&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;createComment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;threads&lt;/code&gt; and &lt;code&gt;comments&lt;/code&gt; imports each return an object of functions that can be passed into the resolver object.&lt;/p&gt;

&lt;p&gt;So what does a resolver function look like? Here is a query resolver that returns all &lt;code&gt;Thread&lt;/code&gt; types from a database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;threads&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;eager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[comments.[user], user]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The function queries a database for the data needed to resolve the &lt;code&gt;Thread&lt;/code&gt; type and then Apollo Server pulls out the values it needs and returns it to the client that requested all the threads.&lt;/p&gt;

&lt;p&gt;A mutation is very similar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;thread&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;eager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;insertAndFetch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;comments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The second parameter a resolver function receives is all the arguments passed from the request. I use those arguments to create a new thread in the database and then return the data for Apollo Server to pass back to the client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Querying the Server
&lt;/h2&gt;

&lt;p&gt;There are many ways to test a GraphQL API. I like to use &lt;a href="https://insomnia.rest/"&gt;Insomnia&lt;/a&gt;. In development mode, Apollo Server will return your schema so that Insomnia can read it, allowing you to auto-complete queries for the API.&lt;/p&gt;

&lt;p&gt;Here is an example query you can send to the server with the above schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;getThreads&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;comments&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In the query, I am requesting the &lt;code&gt;threads&lt;/code&gt; property of the query object and passing in the attributes I want for each thread. Dynamic queries are what make GraphQL so good, because you can ask for as little or as much data as the API can provide. The following json represents what the API server returns to the client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"threads"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Thread 1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"This is the first thread"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"firstName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"lastName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"User 1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"userName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"testuser1"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"comments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"This is a comment on the first thread"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"userName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"testuser2"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Another comment"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"userName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"testuser1"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Thread 2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"This is the second thread"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"firstName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"lastName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"User 2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"userName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"testuser2"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"comments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"This is a comment on the second thread"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"userName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"testuser1"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;A mutation query for creating a thread looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;createThread&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;createThread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A new thread"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"This is a description"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I am calling the &lt;code&gt;createThread&lt;/code&gt; property of the mutation type and passing in the required arguments. It returns to me the resource that it just created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"createThread"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A new thread"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"This is a description"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"firstName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"lastName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"User 1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"userName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"testuser1"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Some General Tips and Tricks
&lt;/h2&gt;

&lt;p&gt;Here are a few more general tips for starting a GraphQL server project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If you use a database, use a NoSQL database like MongoDB or a SQL database with an ORM that supports eager loading. GraphQL types often use nested objects so it can be difficult to write plain SQL queries and map the data for your responses. I used the &lt;a href="https://vincit.github.io/objection.js/"&gt;Objection.js&lt;/a&gt; ORM with sqlite and that made my database code much simpler.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GraphQL naturally validates the data types of any arguments passed into your API, but it only validates the type. By default, a string type can be empty or any length. I used the validation features of Objection.js to prevent the use of empty strings in mutations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;ID&lt;/code&gt; scalar type converts ID values to a string. That will work great for some databases, but in my case I was using sqlite with numeric primary keys so I left my ID values as an &lt;code&gt;Int&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;I was surprised by how quickly you can build a GraphQL API, especially with the help of libraries like Apollo Server and Objection.js. I really like being able to define my API around types which become natural documentation for your available resources. Not having to set up URL routing or type validation saves a lot of time as well. The benefits of GraphQL for building API clients have been touted widely, but I think there are some real advantages for the server too.&lt;/p&gt;

&lt;p&gt;I hope this article helped you understand GraphQL servers even better. Leave a comment if you have any questions or thoughts about this post!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>graphql</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Rewriting My Personal Site with Hugo</title>
      <dc:creator>Andrew Davis</dc:creator>
      <pubDate>Mon, 04 Mar 2019 15:33:50 +0000</pubDate>
      <link>https://dev.to/restoreddev/rewriting-my-personal-site-with-hugo-1708</link>
      <guid>https://dev.to/restoreddev/rewriting-my-personal-site-with-hugo-1708</guid>
      <description>&lt;p&gt;A couple months ago I created my personal website called &lt;a href="https://andrewdavis.me"&gt;andrewdavis.me&lt;/a&gt;. I built it as a custom server side app in Go with MySQL holding the content. I wrote about the experience in &lt;a href="https://andrewdavis.me/post/building-my-personal-site-with-go-and-tailwindcss/"&gt;Building My Personal Site with Go and TailwindCSS&lt;/a&gt;. I enjoyed the project, however, I recently wanted to make some SEO improvements and decided maintaining a custom app was more work than I wanted. I started looking at different static site generators and found &lt;a href="https://gohugo.io/"&gt;Hugo&lt;/a&gt;. It is a really fast site generator that uses Go templates for HTML and Markdown for content. Hugo is very flexible, but also easy to use so I was able to move my site to it in a single day! In fact, I open sourced the code so you can see it all &lt;a href="https://github.com/restoreddev/me"&gt;here on GitHub&lt;/a&gt;. Now, my site is served from HTML files on GitHub Pages, making it much faster at rendering. Here are a few reasons for why I liked Hugo so much and why you may enjoy using it for your next project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Easy to Install and Start a Project
&lt;/h2&gt;

&lt;p&gt;Hugo is a simple binary that &lt;a href="https://gohugo.io/getting-started/installing/"&gt;can be installed&lt;/a&gt; on any OS (I used Homebrew on MacOS &lt;code&gt;brew install hugo&lt;/code&gt;). To start a new project, open a terminal and run &lt;code&gt;hugo new site blog&lt;/code&gt;. Hugo will create a folder called &lt;code&gt;blog&lt;/code&gt; and generate a project skeleton so you can start adding content. To start building templates, add a &lt;code&gt;_default&lt;/code&gt; folder in the &lt;code&gt;layouts&lt;/code&gt; directory. In there you can create a new file called &lt;code&gt;baseof.html&lt;/code&gt; which will become the base template for all your pages. After that you can create an &lt;code&gt;index.html&lt;/code&gt;, &lt;code&gt;list.html&lt;/code&gt; and &lt;code&gt;single.html&lt;/code&gt; template. The index template will be used for the homepage, the list template for any list pages and the single template for content pages.&lt;/p&gt;

&lt;p&gt;Next, you can start adding Markdown in the content folder. You can create Markdown files like &lt;code&gt;post.md&lt;/code&gt; or &lt;code&gt;post/index.md&lt;/code&gt; which will create different paths: &lt;code&gt;/post.html&lt;/code&gt; and &lt;code&gt;/post/&lt;/code&gt; respectively. Each markdown file must have frontmatter, but it can be written in YAML, TOML, or JSON. I wrote mine in TOML, which makes a page look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight markdown"&gt;&lt;code&gt;+++
title = "My Blog Post"
date = "2019-03-01"
+++
The content of my blog post goes here.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To build the pages, you can run &lt;code&gt;hugo server&lt;/code&gt; in your terminal and it will start a server for you to see the site at &lt;code&gt;localhost:1313&lt;/code&gt;. The server will also automatically reload anytime you make changes to your content. Hugo takes the Markdown pages' content and builds them into individual HTML pages using the Go templates. In the template, the Markdown file will be injected using predefined variables so you can use &lt;code&gt;{{ .Title}}&lt;/code&gt; and &lt;code&gt;{{ .Content }}&lt;/code&gt; to indicate where the Markdown data should appear in the template.&lt;/p&gt;

&lt;p&gt;Of course, there is a lot more to templating and content, which you can find in the &lt;a href="https://gohugo.io/content-management/organization/"&gt;docs&lt;/a&gt;. Hugo is very configurable and can do as little or as much as you need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automatic Code Highlighting
&lt;/h2&gt;

&lt;p&gt;On the previous iteration of my site, I used the &lt;a href="https://prismjs.com/"&gt;Prism.js&lt;/a&gt; JavaScript library to enable code highlighting. It worked well, but all the styles are added client side, which is unnecessary work for the browser. Hugo uses a Go syntax highlighter called &lt;a href="https://github.com/alecthomas/chroma"&gt;Chroma&lt;/a&gt; that will add the CSS to the HTML in the build process. To have it run on Markdown codeblocks, just add &lt;code&gt;pygmentsCodefences = true&lt;/code&gt; in the &lt;code&gt;config.toml&lt;/code&gt; in the root of your project. The &lt;code&gt;config.toml&lt;/code&gt; file is the main configuration file used by Hugo when building the site.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrated CSS Processing
&lt;/h2&gt;

&lt;p&gt;I like to use PostCSS for my stylesheets and Hugo works with it easily. I just created a &lt;code&gt;package.json&lt;/code&gt; with &lt;code&gt;postcss-cli&lt;/code&gt; installed and my PostCSS plugins. Then, I created a &lt;code&gt;postcss.config.js&lt;/code&gt; file (not required by Hugo, just what is necessary for PostCSS). Afterwards, I created a CSS file in the assets folder and then imported it into my &lt;code&gt;baseof.html&lt;/code&gt; template using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;{{ $css := resources.Get "site.v01.css" }}
{{ $style := $css | resources.PostCSS }}

&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/css"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{{ $style.Permalink }}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, when I build with Hugo, it will automatically compile my stylesheet and link to it in my base template.&lt;/p&gt;

&lt;h2&gt;
  
  
  Easy Deployment
&lt;/h2&gt;

&lt;p&gt;Hugo has multiple different ways to deploy a site. When you run &lt;code&gt;hugo&lt;/code&gt; in the root of your project, it will build the files in a &lt;code&gt;public&lt;/code&gt; folder. I just followed their guide for &lt;a href="https://gohugo.io/hosting-and-deployment/hosting-on-github/"&gt;deploying to GitHub&lt;/a&gt; and created a &lt;code&gt;publish.sh&lt;/code&gt; script that takes the contents of the public folder and commits it to a separate git branch. The deployment branch is then used by GitHub Pages to serve the files.&lt;/p&gt;

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

&lt;p&gt;I really like that Hugo is straight forward and does not require writing JavaScript to build a static site, like many other generators. Plus, I can now easily update templates and add more features using frontmatter variables without having to write much code. Generated HTML files allow me to not maintain a server setup, decreasing the amount of maintenance time to keep my site going. All in all, I count it as a successful move and plan to use &lt;a href="https://gohugo.io/"&gt;Hugo&lt;/a&gt; in the future!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>go</category>
    </item>
    <item>
      <title>Creating a Magento Theme with Next.js and GraphQL</title>
      <dc:creator>Andrew Davis</dc:creator>
      <pubDate>Tue, 12 Feb 2019 13:43:38 +0000</pubDate>
      <link>https://dev.to/restoreddev/creating-a-magento-theme-with-nextjs-and-graphql-256</link>
      <guid>https://dev.to/restoreddev/creating-a-magento-theme-with-nextjs-and-graphql-256</guid>
      <description>&lt;p&gt;At the end of 2018, Magento released the 2.3.0 version of their e-commerce framework with a new GraphQL API. Traditionally, Magento themes are created with PHP templates, similar to WordPress. However, with the new GraphQL API and &lt;a href="https://magento-research.github.io/pwa-studio/"&gt;PWA Studio&lt;/a&gt;, new themes can be created in JavaScript frontend frameworks like React and Vue. To experiment with the API, I have created an open source theme called &lt;a href="https://github.com/restoreddev/basil"&gt;Basil&lt;/a&gt; using React, Next.js and Apollo. Here is &lt;a href="https://basil.andrewdavis.me"&gt;a preview&lt;/a&gt; of the theme with Magento’s sample catalog. The theme is very experimental so it needs code cleanup and responsive styling, but it allowed me to explore how a theme could be created this way. It does not use any PWA Studio components because I wanted to see what it would take to build a frontend from scratch. Here are my thoughts and impressions about the whole process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deciding on a Framework
&lt;/h3&gt;

&lt;p&gt;There are a ton of options for frontend JavaScript frameworks so I tried to narrow down my choices using two requirements: it must have easy server side rendering for SEO (crucial for e-commerce) and it must support GraphQL. In the end, I tried three frameworks Nuxt.js (Vue), Ember with Fastboot and Next.js (React). Ember actually had my favorite development experience. The code generation CLI and easy templating were a big draw, however, its GraphQL support was wanting. The best Ember GraphQL plugin could not support loading states. Nuxt.js’s GraphQL integration was lacking as well. It was too difficult to get the GraphQL data to load when rendering on the server. In the end, I chose Next.js because of Apollo’s excellent React integration and because Next’s server rendering is top notch. Next will render the whole React component tree with the necessary GraphQL data before outputting the HTML on the server.&lt;/p&gt;

&lt;h3&gt;
  
  
  I like GraphQL
&lt;/h3&gt;

&lt;p&gt;Basil was the first time I have seriously used GraphQL and the development experience was great. The queries are really easy to write and I like that you can store them in files for reuse. It really simplifies retrieving data because you can write queries in a GraphQL client like &lt;a href="https://insomnia.rest/"&gt;Insomnia&lt;/a&gt; and the fields will be auto-populated as you type based on the schema returned from Magento. In React, Apollo makes GraphQL easy by supplying a Query component that you can use to wrap your JSX and your template will be automatically supplied the query results. Here is an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Query&lt;/span&gt; &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;PRODUCT_QUERY&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Error&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;

        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"product__name"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&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="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Routing was a Pain
&lt;/h3&gt;

&lt;p&gt;Magento has a unique routing system because any path underneath the root could map to a category, product or content page. For example, opening &lt;code&gt;/backpack&lt;/code&gt; on a Magento site could take you to a product named Backpack, a category for Backpacks or a content page about backpacks. It is all determined by how the catalog is configured in Magento’s database. To allow for this routing on the frontend client, I had to set up a special wildcard route that would accept any URL path and then query Magento’s &lt;a href="https://devdocs.magento.com/guides/v2.3/graphql/reference/url-resolver.html"&gt;urlResolver&lt;/a&gt; to figure out if the page should display a product, category or content component. Unfortunately, that means two queries have to be run for each catalog page. A framework like Gatsby might be a better option for a small catalog since it can generate a frontend page for each URL in a build step.&lt;/p&gt;

&lt;h3&gt;
  
  
  I Wish Unit Testing React Was Easier
&lt;/h3&gt;

&lt;p&gt;One of the features of Ember I liked was that it came with a unit testing setup and a framework for performing integration tests. Next and React have plenty of examples of how to set up Jest (a test runner), but there is little documentation about good ways to integration test a component that renders HTTP results. I set up &lt;a href="https://airbnb.io/enzyme/"&gt;Enzyme&lt;/a&gt; to help with component rendering and analyzing, but still have not built out a way to mock the GraphQL server for more extensive tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Viability for Magento
&lt;/h3&gt;

&lt;p&gt;Unfortunately, I do not think it is time to make production frontends this way for Magento. Magento’s GraphQL endpoints are lacking and will not be fleshed out until &lt;a href="https://github.com/magento/graphql-ce/wiki/Roadmap"&gt;later this year&lt;/a&gt;. Currently, to build a cart and checkout, you would have to fallback on the old REST API. I think it would be better to wait until the GraphQL API has better frontend coverage. Even when it does cover the checkout, it will still be missing some of the smaller Magento features like related products and wish lists. Magento is still working on their frontend solution, &lt;a href="https://magento-research.github.io/pwa-studio/"&gt;PWA Studio&lt;/a&gt;, as well. When it is feature complete, PWA Studio will be another option as a basis for a JavaScript frontend.&lt;/p&gt;

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

&lt;p&gt;The new GraphQL support is exciting because it will allow Magento developers to make modern and unique frontend experiences. However, there is a lot of development to be accomplished before it is production ready. While I will miss the simplicity of PHP templates, the performance and capabilities that JavaScript frameworks provide will make them popular for many merchants. Plus, it will make it much easier to introduce frontend developers to the Magento ecosystem.&lt;/p&gt;

&lt;p&gt;Let me know if you have any questions about my experience with making Basil. Also, check out the &lt;a href="https://github.com/restoreddev/basil"&gt;GitHub repo&lt;/a&gt; and the &lt;a href="https://basil.andrewdavis.me/"&gt;online preview&lt;/a&gt; and let me know what you think!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
      <category>magento</category>
    </item>
    <item>
      <title>Announcing PHP Apprentice!</title>
      <dc:creator>Andrew Davis</dc:creator>
      <pubDate>Fri, 11 Jan 2019 13:42:58 +0000</pubDate>
      <link>https://dev.to/restoreddev/announcing-php-apprentice-coc</link>
      <guid>https://dev.to/restoreddev/announcing-php-apprentice-coc</guid>
      <description>&lt;p&gt;I am excited to finally announce &lt;a href="https://phpapprentice.com"&gt;PHP Apprentice&lt;/a&gt;! It is an online, free and open-source book for learning the PHP programming language. The book is a side project I have been building for six months. My goal is to provide a contemporary resource for learning the basics of PHP with a focus on high quality code. PHP has been around for 25 years and has changed a lot since its inception. A lot of the resources for writing good PHP have not aged well or are inapplicable today. I wrote PHP Apprentice to remedy the lack of available websites for learning PHP.&lt;/p&gt;

&lt;p&gt;Currently, PHP Apprentice has chapters on the basic building blocks of the language, but in the future I will be adding sections on generating webpages, connecting to databases and advanced  techniques like using Composer and autoloading. I am looking for feedback so please leave a comment here or an issue on the &lt;a href="https://github.com/restoreddev/phpapprentice"&gt;repository&lt;/a&gt; if you have any thoughts or requests.&lt;/p&gt;

&lt;p&gt;Each chapter in PHP Apprentice was written as a Markdown file. I then built an HTML generator in PHP that takes each file and parses it with &lt;a href="https://parsedown.org/"&gt;Parsedown&lt;/a&gt; into an HTML chunk and loads them with a template into a full HTML page. The pages are then served by GitHub pages. The build process can be performed using a CLI command so I automated the deployment using &lt;a href="https://travis-ci.com/"&gt;Travis CI&lt;/a&gt;. Whenever any code is merged into &lt;code&gt;master&lt;/code&gt;, Travis will pick it up, re-build all the webpages and push them to another branch on the repository which is used by GitHub Pages.&lt;/p&gt;

&lt;p&gt;The frontend is all plain HTML, CSS and JavaScript. I used &lt;a href="https://postcss.org/"&gt;PostCSS&lt;/a&gt; to add file imports and variables. The code highlighting is performed by &lt;a href="https://prismjs.com/"&gt;Prism.js&lt;/a&gt;.  I wanted the focus of each page to be on the code so the styling is very minimal. The site is responsive, but has room to improve the experience on mobile. I focused on desktop since I recommend writing the code in the chapters while reading the book.&lt;/p&gt;

&lt;p&gt;PHP Apprentice was inspired by &lt;a href="https://elixirschool.com"&gt;Elixir School&lt;/a&gt; and &lt;a href="https://gobyexample.com/"&gt;Go by Example&lt;/a&gt;, two sites I admire for their clarity and quality. I hope that PHP Apprentice will become a similarly helpful site for the PHP ecosystem. It is a living book so I will be changing and improving the site over time.&lt;/p&gt;

&lt;p&gt;Please check out &lt;a href="https://phpapprentice.com/"&gt;PHP Apprentice&lt;/a&gt; and let me know what you think! &lt;/p&gt;

</description>
      <category>php</category>
      <category>showdev</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building My Personal Site with Go and TailwindCSS</title>
      <dc:creator>Andrew Davis</dc:creator>
      <pubDate>Mon, 17 Dec 2018 01:57:00 +0000</pubDate>
      <link>https://dev.to/restoreddev/building-my-personal-site-with-go-and-tailwindcss-5bhn</link>
      <guid>https://dev.to/restoreddev/building-my-personal-site-with-go-and-tailwindcss-5bhn</guid>
      <description>&lt;p&gt;Recently, I found the domain &lt;a href="https://andrewdavis.me"&gt;andrewdavis.me&lt;/a&gt; available for purchase. I tried to buy it in the past, but it was already taken. I quickly purchased the domain, but then I had to decide what to put on it. I made up my mind to build a personal website that would showcase my work and writing. However, I wanted to use it as a learning opportunity and build the site in something unconventional. The two most popular solutions for building a personal site are WordPress or a static site generator. I wanted something in the middle, a site with a backend for post writing and a custom frontend with few dependencies. I built the site using &lt;a href="https://golang.org/"&gt;Go&lt;/a&gt; with a couple frontend packages including &lt;a href="https://tailwindcss.com/"&gt;TailwindCSS&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Backend in Go with Gin
&lt;/h2&gt;

&lt;p&gt;I decided to use Go for the backend. In the last few years, Go has become very popular for server apps, particularly micro-services. I chose &lt;a href="https://github.com/gin-gonic/gin"&gt;Gin&lt;/a&gt; as a web framework to help with routing and serving templates. Gin has a Sinatra-like syntax that allows you to express a route as a HTTP method and a function to be called for the route.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;router&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusOK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"index.html"&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;I also pulled in &lt;a href="http://gorm.io/"&gt;Gorm&lt;/a&gt; for database access. Gorm allows you to write your tables as Go structs and it will build the columns from the struct fields. Then, you can easily query records based on your struct.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Post&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;gorm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Content&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`gorm:"type:text;"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="n"&gt;Post&lt;/span&gt;
&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;First&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;All in all, I was successful using Go to build the backend. I like the safety you get with data types and compile checks. The beauty of Go is that if you can get the code to compile, then you have more confidence the app will work. It is also very fast. However, most of the request time is spent querying the database anyway so the real world speed boost is not a significant difference from PHP or Ruby. I had to piece together several packages to get all the features I need, but there are other Go frameworks like &lt;a href="https://gobuffalo.io"&gt;Buffalo&lt;/a&gt; that offer a more Rails-like experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frontend with TailwindCSS, SimpleMDE, Stimulus and Prism
&lt;/h2&gt;

&lt;p&gt;I used &lt;a href="https://tailwindcss.com/"&gt;TailwindCSS&lt;/a&gt; as my styling framework. I have become a huge fan of Tailwind for all of my personal projects. It takes a little time to adapt to a utility framework, but I love the flexibility and features you get from it. It allows me to build a unique website without much custom CSS. Plus, it comes with some great default color schemes and font stacks.&lt;/p&gt;

&lt;p&gt;I used &lt;a href="https://simplemde.com/"&gt;SimpleMDE&lt;/a&gt; on the backend to give me a Markdown editor. It was very easy to setup and has worked with no problems.&lt;/p&gt;

&lt;p&gt;Also on the backend, I used &lt;a href="https://stimulusjs.org/"&gt;Stimulus&lt;/a&gt; to help me build in a little more interactivity. Stimulus is an excellent framework for server rendered HTML and has become a replacement replacement for jQuery when I need some JavaScript &lt;a href="https://twitter.com/dhh/status/958442395317583872?lang=en"&gt;sprinkles&lt;/a&gt;. Stimulus is easy to learn and is also much easier to keep organized than jQuery.&lt;/p&gt;

&lt;p&gt;Lastly, I used &lt;a href="https://prismjs.com/"&gt;Prism&lt;/a&gt; on the frontend to highlight code blocks. It was also easy to set up and run. It allows you to pick which languages you need for highlighting and gives you the options to pick a theme (Tomorrow Night for the win!).&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://andrewdavis.me"&gt;andrewdavis.me&lt;/a&gt; is up and running now so please check it out and let me know what you think! While my primary blogging platform is Dev.to, I enjoy having my own site to show my skills and writing. I plan to add a few more pages showing my current projects and past work. I think a personal site is a great way to experiment with new patterns and have some fun with new languages. What languages and libraries have you used for your personal sites?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>go</category>
    </item>
    <item>
      <title>Showing Kindness while Programming</title>
      <dc:creator>Andrew Davis</dc:creator>
      <pubDate>Tue, 20 Nov 2018 14:34:14 +0000</pubDate>
      <link>https://dev.to/restoreddev/showing-kindness-while-programming-52a7</link>
      <guid>https://dev.to/restoreddev/showing-kindness-while-programming-52a7</guid>
      <description>&lt;p&gt;Software development and programming is a difficult profession. It is very new and requires a lot of practice, learning and mental focus. It can get frustrating when you are working with others and mistakes are made. Programmers are also very demanding of those who provide our programming languages and frameworks, especially with bugs or problems that hinder our daily work. When we encounter these problems, it is very tempting to get angry and make a snide comment on social media or give a dirty look in the office. &lt;/p&gt;

&lt;p&gt;An angry response is not what we need in development. Showing patience with new developers allows them room to grow without fear of retribution. Being kind to vendors allows them the mental energy to improve their product or framework. Forgiving mistakes improves the emotional health of your team and their ability to code incredible features. To encourage patience, here are my thoughts on how we can better show kindness in software development.&lt;/p&gt;

&lt;h3&gt;
  
  
  Be Patient with Junior Developers
&lt;/h3&gt;

&lt;p&gt;Being a junior developer is very difficult. There is so much to learn when starting to develop software and it goes beyond just knowing how to use a programming language. A junior developer has to learn how to work on a team, understand software requirements, solve problems and communicate with non-technical stakeholders. It is very intimidating and takes several years for a junior developer to even begin to master these different areas, not to mention keeping up with programming trends. Therefore, it is key for more experienced developers and managers to show patience with junior developers as they learn. For a junior developer to find confidence in their work, they do not need to be afraid of failing. They need to be able to fail and be instructed, with kindness, about how to prevent the mistake again.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do Not Mock Someone for their Chosen Language or Framework
&lt;/h3&gt;

&lt;p&gt;We developers are very opinionated about what is the best programming language or framework to use. Having opinions and healthy debates is a good thing and allows the programming community to grow with even better features and tools. However, we need to stop mocking each other for building a product or tool in a given language or framework just because we do not like it. I see this a lot in the JavaScript and PHP communities. We criticize each other for using React or Vue or Angular or (heaven forbid) jQuery! PHP developers are mocked for their language’s inconsistencies. These criticisms are not constructive and just discourage developers from building. At the end of the day, it doesn’t matter if you like React or Ember when you are making successful software.&lt;/p&gt;

&lt;h3&gt;
  
  
  Be Considerate with Open Source Maintainers
&lt;/h3&gt;

&lt;p&gt;Our profession is very unique in that it relies a lot on free frameworks and tools provided by volunteers. Since open source tools are built out in the open, we also have more access to the maintainers and creators behind them. It can get very tempting to send an angry comment to maintainers on Twitter or GitHub when their framework breaks. An open source developer is often unpaid in their contributions so they do not deserve our ire or disrespect. Even if they are being paid, showing anger does not help them fix a problem. Being kind and giving respectful feedback is key to the project being successful and the maintainers not getting burned out on their work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Show Forgiveness when Something Breaks
&lt;/h3&gt;

&lt;p&gt;When something goes wrong with your application, it can be really easy to start the blame game. Who pushed the code? What did they screw up? Why were they not more careful? These kinds of questions are unhelpful and hurtful to whoever receives the blame. Instead of blaming, we need to focus on what went wrong and how we can help each other not make that mistake again. Maybe we need a better unit testing setup? Maybe we need better documentation of this feature? Should we test more thoroughly after deploying code? Questions like these are constructive and help programmers recover more quickly from mistakes and stay confident in their work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Celebrate Victories
&lt;/h3&gt;

&lt;p&gt;When development is going well, it is easily taken for granted. As a result, we often do not display an emotional reaction until a bug happens or a customer complains. To increase programming morale, it is important to regularly celebrate accomplishments. Success is very satisfying and helps programmers stay motivated and avoid burnout. Next time you achieve a new feature, celebrate it! Even if the reward is just a box of cookies and some high fives.&lt;/p&gt;

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

&lt;p&gt;Being kind and forgiving is a conscious choice that we need to encourage in our development teams. It allows for developers to learn more quickly, prevent mistakes and enjoy work. Kindness is a cure for burnout and exhaustion and encourages fresh ideas and unique features. Being patient with others is not easy, but essential for happy and successful teams. Next time you work with another programmer, I encourage you to think about how you can be more kind and patient with them. It will make your work more fulfilling in a way you may not have already experienced.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>career</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Writing Beautiful Code</title>
      <dc:creator>Andrew Davis</dc:creator>
      <pubDate>Mon, 24 Sep 2018 14:28:54 +0000</pubDate>
      <link>https://dev.to/restoreddev/writing-beautiful-code-10p6</link>
      <guid>https://dev.to/restoreddev/writing-beautiful-code-10p6</guid>
      <description>&lt;p&gt;Because programming is a technical profession, we often approach it without thought to design. Code is for getting a computer to do what we need, why should design matter? The majority of the programming languages we use were built for the programmer and are transformed into something that is optimized for the computer. As a result, we need to write our code, not just for the compiler or interpreter, but for humans to read. To make code readable, I approach it as an art. When you treat code as art, it becomes quickly digestible and easy to extend. Creative code also reduces bugs because it is easier to understand what it is executing.&lt;/p&gt;

&lt;p&gt;The problem with artful coding is that it is not easy to do. Oftentimes, it is hard enough to get the code to work in the first place, much less be creative! However, just like any art form, there are some basic techniques we can follow to write well designed code. I am still exploring the best ways to write beautiful code, but these steps are what I follow to bring a little art to my programming.&lt;/p&gt;

&lt;h3&gt;
  
  
  Start with a Unit Test
&lt;/h3&gt;

&lt;p&gt;Test Driven Development is not universally liked, but I find it to be a very good practice. Not only does it ensure all your code is tested, it also forces you to think about how your code will be used before writing it. In these examples, let’s imagine we are writing an email client in PHP and we want to be creative in the client’s design. Let’s start with a unit test for sending an email:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailClientTest&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nc"&gt;PHPUnit\Framework\TestCase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;test_sending_an_email&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nf"&gt;Email\Client&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nv"&gt;$emailMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nf"&gt;Email\Message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Hello world!'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'andrew@dev.to'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$emailMessage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertTrue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="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;Since we wrote the unit test first, we already know how we want the code to be shaped. We know we will have an &lt;code&gt;Email&lt;/code&gt; namespace with two classes representing the &lt;code&gt;Client&lt;/code&gt; and the &lt;code&gt;Message&lt;/code&gt;. We also know that we will have a &lt;code&gt;send&lt;/code&gt; method for the process of submitting the email message with the client. In the unit test, we also decided how the pieces of our code will be named, which brings us to my next point.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Grammar when Naming Variables and Methods
&lt;/h3&gt;

&lt;p&gt;Programmers often joke that naming things is hard and it’s the truth! However, naming a piece of code is not just hard, it’s also very important. How code is named determines how quickly a developer can understand it, reducing bugs and development time.  In the above example, we decided to put all of our code in the Email namespace which is very clear about what it contains. Next, we chose &lt;code&gt;Client&lt;/code&gt; to represent the object that sends messages and &lt;code&gt;Message&lt;/code&gt; for the email itself, both descriptive nouns. Finally, we call a &lt;code&gt;send&lt;/code&gt; method which is a verb commonly associated with email. Now, we see a good pattern: use nouns for class names and verbs for methods.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep Your Functions Small
&lt;/h3&gt;

&lt;p&gt;It is tempting to put all the code for an operation in a single function. However, it’s really important to break it up into small chunks for readability and testability. Let’s use the &lt;code&gt;send&lt;/code&gt; method as an example.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$emailAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Message&lt;/span&gt; &lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Validate parameters&lt;/span&gt;
        &lt;span class="nv"&gt;$validateEmail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;filter_var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$emailAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;FILTER_VALIDATE_EMAIL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$validateMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$validateEmail&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$validateMessage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Communicate with email server&lt;/span&gt;
        &lt;span class="nv"&gt;$curl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;curl_init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'https://mail.example.com'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_POST&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="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_POSTFIELDS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'to'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$emailAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'text'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;curl_exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nb"&gt;curl_close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method is straightforward, but cluttered. It’s a little difficult to understand, so we added some comments so the reader knows what is happening. However, what if we created a new method instead of a comment?&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$emailAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Message&lt;/span&gt; &lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;validateParameters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$emailAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;sendToMailServer&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="s1"&gt;'to'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$emailAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'text'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;validateParameters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$emailAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Message&lt;/span&gt; &lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$validateEmail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;filter_var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$emailAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;FILTER_VALIDATE_EMAIL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$validateMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$validateEmail&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$validateMessage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;sendToMailServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$params&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$curl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;curl_init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'https://mail.example.com'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_POST&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="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CURLOPT_POSTFIELDS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;curl_exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nb"&gt;curl_close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$curl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$result&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;Our &lt;code&gt;send&lt;/code&gt; method is now much cleaner. The other functions perform a single task with less than 10 lines of code each, making them easy to read.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use a Style Guide
&lt;/h3&gt;

&lt;p&gt;Finally, I recommend using a style guide for your chosen programming language. For PHP, I like to use the &lt;a href="https://www.php-fig.org/psr/psr-2/"&gt;PSR-2&lt;/a&gt; FIG standard for my code. The FIG standard is widely recognized and used by popular PHP frameworks like Laravel and Symfony. Plus, the Symfony team has released a CLI utility that automagically reformats your code to follow PSR-2: &lt;a href="https://cs.sensiolabs.org/"&gt;PHP Coding Standards Fixer&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;Designing code requires effort and practice, but reaps many rewards. It causes your code to be in smaller, more readable chunks and reduces bugs by bringing clarity and focus. To continue learning more, I recommend reading code that is well designed. The &lt;a href="https://github.com/laravel/framework"&gt;Laravel&lt;/a&gt; and &lt;a href="https://github.com/rails/rails"&gt;Ruby on Rails&lt;/a&gt; codebases are both examples of clean code that is treated with an artful touch. Do some source diving in both to learn more!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>productivity</category>
      <category>php</category>
    </item>
    <item>
      <title>What libraries do you like to use to write unit and integration tests for React Native? Any TDD advocates using React Native?</title>
      <dc:creator>Andrew Davis</dc:creator>
      <pubDate>Thu, 13 Sep 2018 02:40:39 +0000</pubDate>
      <link>https://dev.to/restoreddev/what-libraries-do-you-like-to-use-to-write-unit-and-integration-tests-for-react-native-any-tdd-advocates-using-react-native-25c2</link>
      <guid>https://dev.to/restoreddev/what-libraries-do-you-like-to-use-to-write-unit-and-integration-tests-for-react-native-any-tdd-advocates-using-react-native-25c2</guid>
      <description>&lt;p&gt;I am currently working on a React Native project for the first time. I used &lt;code&gt;react-native init&lt;/code&gt; so I have Jest which I can use for snapshot testing. However, what do you like to use for integration testing, like filling out fields and submitting buttons? I would like to find a workflow that works well with TDD if possible.&lt;/p&gt;

</description>
      <category>discuss</category>
    </item>
  </channel>
</rss>
