<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Jesse Rushlow</title>
    <description>The latest articles on Forem by Jesse Rushlow (@jrushlow).</description>
    <link>https://forem.com/jrushlow</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%2F303094%2Fef81b1b8-5b93-49ce-bbb8-6f70a94251c9.jpeg</url>
      <title>Forem: Jesse Rushlow</title>
      <link>https://forem.com/jrushlow</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jrushlow"/>
    <language>en</language>
    <item>
      <title>You want to base what on my hmac?</title>
      <dc:creator>Jesse Rushlow</dc:creator>
      <pubDate>Mon, 09 Mar 2020 02:26:58 +0000</pubDate>
      <link>https://forem.com/jrushlow/you-want-to-base-what-on-my-hmac-3k51</link>
      <guid>https://forem.com/jrushlow/you-want-to-base-what-on-my-hmac-3k51</guid>
      <description>&lt;h1&gt;
  
  
  A guide to shrinking an elephant hashed and encoded in PHP.
&lt;/h1&gt;

&lt;p&gt;I was recently working on a new bundle for Symfony, and while reviewing a block of code I had written earlier I asked my self, why do the big guys (Symfony and Laravel) encode the binary output of &lt;code&gt;hash_hmac()&lt;/code&gt; using &lt;code&gt;base64_encode()&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;After some digging around, I discovered the answer. But first lets take a look at how &lt;code&gt;hash_hmac()&lt;/code&gt; works. More specifically, what &lt;code&gt;hash_hmac()&lt;/code&gt; returns...&lt;/p&gt;

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

&lt;p&gt;When overhead is a concern, using &lt;code&gt;base64_encode(hash_hmac(..., true))&lt;/code&gt; gives you a hash with a string length of 44 characters vs the 64 characters that &lt;code&gt;hash_hmac(..., false)&lt;/code&gt; provides.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is this hash hmac and why do I care about it?
&lt;/h2&gt;

&lt;p&gt;From the manual - "hash_hmac — Generate a keyed hash value using the HMAC method"&lt;/p&gt;

&lt;p&gt;Translation, this method allows us to take a string of data, and potentially create a cryptographically secure hash that can be used to verify the data integrity. One thing to remember about &lt;code&gt;hash_hmac&lt;/code&gt;, it's selfish. &lt;code&gt;hash_hmac&lt;/code&gt; takes the data and gives you a string (hash), but it will never give you the data used to create that hash.&lt;/p&gt;

&lt;p&gt;This is sometimes referred to as a one-way hash. Meaning the only way we can verify the integrity and authenticity of the data, is to create a new hash and then compare the original hashed value against our newly created hash. To do this we use the &lt;code&gt;hash_equals()&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;To put it another way, lets play the game telephone. You remember that as a kid right? A large group gets in a circle and then the first kid says to his buddy on the left, "elephants are gray". Then his buddy does the same to the kid to his left, and so on and so on. The point of that game is to see if the phrase is still the same by the time it circles back around to the first kid.&lt;/p&gt;

&lt;p&gt;Only in our version of the game, I'm going to start the game and use &lt;code&gt;hash_hmac&lt;/code&gt; to prove to everyone at the end, I'm not fibbing...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$elephantHash = hash_hmac('sha256', 'elephants are gray', 'secret_key'); 
var_dump($elephantHash);
// string(64) d53c1002ddf2159b926ae4eaf775fb0242282e826070bb79a899bbf1af45642f

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So the phrase is "elephants are gray", go tell a friend what the phrase is and have them repeat it to me. Hurry, I'm waiting...&lt;/p&gt;

&lt;p&gt;While I'm waiting to hear back from your friend, I'll show you how I'm going to verify the original phrase. First, there are 3 required arguments &lt;code&gt;hash_hmac()&lt;/code&gt; needs. The first is the algorithm, &lt;code&gt;algo&lt;/code&gt;, that will be used to create the hash. &lt;code&gt;sha256&lt;/code&gt; is a good place to start, but be sure to follow best practices when picking which algorithm best fits your use case.&lt;/p&gt;

&lt;p&gt;The second argument is the &lt;code&gt;data&lt;/code&gt; string. This string is what will actually be hashed. In our case, we are hashing 'elephants are gray'. Lastly, we have to provide the third, &lt;code&gt;key&lt;/code&gt;, argument that is used to generate the hash. The key, similar to a salt, must be kept secret. If you're using a framework like Symfony, &lt;code&gt;APP_SECRET&lt;/code&gt; could be used as your key. So long as it's never exposed.&lt;/p&gt;

&lt;p&gt;There is a 4th optional argument to &lt;code&gt;hash_hmac()&lt;/code&gt;, &lt;code&gt;raw_output&lt;/code&gt;, but I'll get to that later. Meanwhile, let's see what happens when we create a second hash using 'elephants are gray' as the data string again and compare it to the first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// verifyElephantColor()
$secondGrayElephant = hash_hmac('sha256', 'elephants are gray', 'secret_key');

function verifyElephantColor($knownElephant, $suspiciousElephant): string
{
    if (hash_equals($knownElephant, $suspiciousElephant) {
        return 'We have 2 gray elephants';
    }

    return 'Ooops, one of the elephants changed color';
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;verifyElephantColor()&lt;/code&gt; method above would return &lt;code&gt;We have 2 gray elephants&lt;/code&gt;. This is because our, &lt;code&gt;$secondGrayElephant&lt;/code&gt;, is using the same algorithm, data, and key as &lt;code&gt;$elephantHash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That was quick! Your friend just said to me 'elephants are pink'. Hmm, something seems fishy about this. I don't remember telling you the PHP elephant is pink... Let's find out for sure by calling the &lt;code&gt;verifyElephantColor()&lt;/code&gt; method again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$pinkElephant = hash_hmac('sha256', 'elephants are pink', 'secret_key');
echo verifyElephantColor($elephantHash, $pinkElephant);

// Ooops, one of the elephants changed color

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;AH HA! See, I never said elephants are pink! Since the &lt;code&gt;data&lt;/code&gt; supplied to &lt;code&gt;hash_hmac()&lt;/code&gt; differs from the original data used to create &lt;code&gt;$elephantHash&lt;/code&gt;, we are given a different hashed string. The same holds true if a different &lt;code&gt;algo&lt;/code&gt; or &lt;code&gt;key&lt;/code&gt; were used.&lt;/p&gt;

&lt;h2&gt;
  
  
  How can we leverage PHP to shrink an elephant?
&lt;/h2&gt;

&lt;p&gt;Now that you know how to create a hash with &lt;code&gt;hash_hmac&lt;/code&gt; and verify the hash with another, using &lt;code&gt;hash_equals()&lt;/code&gt;, let's see if we can get that elephant to shed a pound or two. Remember that fourth and optional argument, &lt;code&gt;raw_output&lt;/code&gt;, I mentioned earlier? The documentation states that when &lt;code&gt;raw_output&lt;/code&gt; is set to &lt;code&gt;true&lt;/code&gt;, it will return raw binary data. Let's have a look at that...&lt;/p&gt;

&lt;h3&gt;
  
  
  Inner workings of hash_hmac:
&lt;/h3&gt;

&lt;p&gt;Diving into the PHP source code, specifically &lt;code&gt;php-src/ext/hash/hash.c&lt;/code&gt;, we eventually find the &lt;code&gt;hash_hmac&lt;/code&gt; declaration and see that it calls the internal &lt;code&gt;php_hash_do_hash_hmac()&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PHP_FUNCTION(hash_hmac)
{
    php_hash_do_hash_hmac(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Without getting into the nitty gritty of exactly how the &lt;code&gt;php_hash_do_hash_hmac&lt;/code&gt; function generates a hash, we can skip down to the return logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//php_hash_do_hash_hmac()

if (raw_output) {
    ZSTR_VAL(digest)[ops-&amp;gt;digest_size] = 0;
    RETURN_NEW_STR(digest);
} else {
    zend_string *hex_digest = zend_string_safe_alloc(ops-&amp;gt;digest_size, 2, 0, 0);

    php_hash_bin2hex(ZSTR_VAL(hex_digest), (unsigned char *) ZSTR_VAL(digest), ops-&amp;gt;digest_size);
    ZSTR_VAL(hex_digest)[2 * ops-&amp;gt;digest_size] = 0;
    zend_string_release_ex(digest, 0);
    RETURN_NEW_STR(hex_digest);
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then strip away some of that C code that is irrelevant in the context of this explanation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (raw_output) {
    RETURN_NEW_STR(digest);
} else {
    php_hash_bin2hex(ZSTR_VAL(hex_digest), (unsigned char *) ZSTR_VAL(digest), ops-&amp;gt;digest_size);
    RETURN_NEW_STR(hex_digest);
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When we call &lt;code&gt;hash_hmac()&lt;/code&gt; in PHP, the 4th &lt;code&gt;raw_output&lt;/code&gt; argument is used in this if/else block. So if &lt;code&gt;raw_output&lt;/code&gt; = &lt;code&gt;true&lt;/code&gt;, &lt;code&gt;php_hash_do_hash_hmac()&lt;/code&gt; returns us a nice chunk of binary code. If your business logic consumes binary, proceed no further. If binary isn't in your taste buds, use the default value, &lt;code&gt;false&lt;/code&gt;, for &lt;code&gt;raw_output&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When &lt;code&gt;raw_output&lt;/code&gt; = &lt;code&gt;false&lt;/code&gt;, we can see that the &lt;code&gt;digest&lt;/code&gt; (binary representation) is passed to &lt;code&gt;php_hash_bin2hex()&lt;/code&gt; who's return value is ultimately returned by &lt;code&gt;php_hash_do_hash_hmac()&lt;/code&gt;. Sound familiar? &lt;code&gt;php_hash_bin2hex()&lt;/code&gt; is actually the internal function called by &lt;code&gt;bin2hex()&lt;/code&gt; that we use in userland code.&lt;/p&gt;

&lt;p&gt;In short, &lt;code&gt;hash_hmac()&lt;/code&gt; returns either a binary or hexit representation of the &lt;code&gt;data&lt;/code&gt; passed to the function depending on the value of &lt;code&gt;raw_output&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ok, I'm not seeing the point yet...
&lt;/h3&gt;

&lt;p&gt;Don't worry, I'm getting to it now. Using the example from above -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$elephantHash = hash_hmac('sha256', 'elephants are gray', 'secret_key'); 
var_dump($elephantHash);
// string(64) d53c1002ddf2159b926ae4eaf775fb0242282e826070bb79a899bbf1af45642f

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We now know that our &lt;code&gt;$elephantHash&lt;/code&gt; value is actually a 64 character length string that was ultimately returned from &lt;code&gt;bin2hex()&lt;/code&gt;. I'm a huge fan of using the least amount of data possible, especially when I have to store that data in a data store such as MySQL.&lt;/p&gt;

&lt;p&gt;Let's try this instead -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$elephantHash = hash_hmac('sha256', 'elephants are gray', 'secret_key', true);
// $elephantHash &amp;lt;- binary representation of the hashed 'elephants are gray` data string because we set true as the raw_data argument.

$skinnyElephant = base64_encode($elephantHash);
var_dump($skinnyElephant);
// string(44) "1TwQAt3yFZuSauTq93X7AkIoLoJgcLt5qJm78a9FZC8="

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;$skinnyElephant&lt;/code&gt; has a string length of 44 characters while &lt;code&gt;$elephantHash&lt;/code&gt; is 64 characters.&lt;/p&gt;

&lt;h3&gt;
  
  
  Holy Elephant, you've lost 20 characters! How can this be?!
&lt;/h3&gt;

&lt;p&gt;In a brief discussion with Sara Golemon, one of PHP's core developers, she provided 2 key takeaways in respect to encoding the binary result of &lt;code&gt;hash_hmac()&lt;/code&gt; using &lt;code&gt;base64_encode()&lt;/code&gt; vs &lt;code&gt;hash_hmac(..., false)&lt;/code&gt;;&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Neither version is more or less secure than the other. Each has effectively* 256 bits of entropy.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;bin2hex() increases the size of the string its given by 2:1, base64_encode() increases the size of the input by about 4:3**.&lt;/p&gt;

&lt;p&gt;* It's actually slightly lower than 256bit for math reasons, but the actual entropy of both is precisely equal. They're just different representations of the same data.&lt;/p&gt;

&lt;p&gt;** Depends on input block alignment which is based on 3 octets. sha256 isn't an exact multiple of blocks, so the expansion is actually 11:8, which is still well below 2:1.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why does any of this matter?
&lt;/h2&gt;

&lt;p&gt;As we can see above, using &lt;code&gt;base64_encode(hash_hmac(..., true))&lt;/code&gt; results in, approximately, a 31% smaller "footprint" as compared to using &lt;code&gt;hash_hmac(..., false)&lt;/code&gt;. If you're developing an application that doesn't care about how much storage space, or I/O is being utilized in a data store, then either of the 2 method's will suite your needs perfectly fine.&lt;/p&gt;

&lt;p&gt;However, if scalability, storage space, network performance, etc... are of any concern to you, use &lt;code&gt;base64_encode(hash_hmac(..., true))&lt;/code&gt;. This will ultimately reduce overhead and utilize less space in persistence while, theoretically speeding up network calls and app performance. The smaller the data, the faster the data can be consumed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Footnote
&lt;/h2&gt;

&lt;p&gt;I'm not a security expert... I'm a developer just like you. Use the information I have conveyed in this article with a bit of common sense. I.e. don't go using &lt;code&gt;hash_emac('sha256'...)&lt;/code&gt; to secure the admin panel of your retirement fund... You get the picture.&lt;/p&gt;

&lt;p&gt;Lastly I'd like to thank Sara Golemon for taking a few minutes to verify and answer a few thoughts/questions I had that led up to this article. Keep up the great work you do for the PHP community!&lt;/p&gt;

&lt;p&gt;As always, any comments, questions, and/or constructive criticism are always welcome.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jesse Rushlow &lt;code&gt;jr (at) rushlow (dot) dev&lt;/code&gt; &lt;a href="https://twitter.com/JesseRushlow"&gt;@JesseRushlow&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>php</category>
      <category>hashhmac</category>
      <category>encoding</category>
    </item>
    <item>
      <title>Oops, I forgot to sign my commit from last Monday...</title>
      <dc:creator>Jesse Rushlow</dc:creator>
      <pubDate>Tue, 28 Jan 2020 13:44:17 +0000</pubDate>
      <link>https://forem.com/jrushlow/oops-i-forgot-to-sign-my-commit-from-last-monday-2jke</link>
      <guid>https://forem.com/jrushlow/oops-i-forgot-to-sign-my-commit-from-last-monday-2jke</guid>
      <description>&lt;h2&gt;
  
  
  How to interactively use git rebase to fix unsigned GPG commits.
&lt;/h2&gt;

&lt;p&gt;This is mainly a "post-it note to self" as I usually don't forget to sign my git commits, but occasionally I run into issues where I don't notice a commit has not been signed until 30 commits later. Here's the solution...&lt;/p&gt;

&lt;h3&gt;
  
  
  TL;DR
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;git rebase -i ID_OF_COMMIT_BEFORE_FIX&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;change &lt;code&gt;pick&lt;/code&gt; to &lt;code&gt;edit&lt;/code&gt; for the commit(s) needing a GPG signature and save.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git commit --amend --no-edit -S&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git rebase --continue&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  The Backstory
&lt;/h3&gt;

&lt;p&gt;In my usual workflow, especially when working with software that utilizes Git Flow like branches, I use GitKraken for visualization of the git structure.It has a nice UI and does a great job at presenting git repositories. But it does lack some "advanced" features to be truly useful to me. Such as handling complex GPG / SSH key setup's. (More on that in a future post)&lt;/p&gt;

&lt;p&gt;This morning I was working on &lt;a href="https://github.com/geeshoe/atom"&gt;geeshoe/atom&lt;/a&gt;, a PHP library to to generate fully compliant RFC4287 RSS/Atom feeds (Currently in initial development). I had mistakenly performed a cherry pick using GitKraken. I say mistakenly because as I mentioned previously, GitKraken doesn't recognize my GPG key setup, so while it did perform the cherry pick, GitKraken didn't actually sign the commit. I didn't notice this until after I had pushed a PR up to GitHub and seen one of my commits didn't have the green "verified" tag. Dang it!&lt;/p&gt;




&lt;h3&gt;
  
  
  Are my commits signed?
&lt;/h3&gt;

&lt;p&gt;In the CLI, &lt;code&gt;git log --show-signature&lt;/code&gt; let's you know...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
user@host:~/document$ git log --show-signature

commit 4ff30a5... (HEAD -&amp;gt; master)
gpg: Signature made Tue 28 Jan 2020 05:36:27 AM EST
gpg: using RSA key ...741096D2ADE04CA
gpg: Good signature from "Jesse Rushlow &amp;lt;jr@geeshoe.com&amp;gt;" [ultimate]
Author: Jesse Rushlow &amp;lt;jr@geeshoe.com&amp;gt;
Date: Tue Jan 28 05:36:01 2020 -0500

    updated doc

commit 95f8587...
Author: Jesse Rushlow &amp;lt;jr@rushlow.dev&amp;gt;
Date: Tue Jan 28 05:21:15 2020 -0500

    ignore ideas

commit c772d80d...
gpg: Signature made Tue 28 Jan 2020 05:19:33 AM EST
gpg: using RSA key ...741096D2ADE04CA
gpg: Good signature from "Jesse Rushlow &amp;lt;jr@geeshoe.com&amp;gt;" [ultimate]
Author: Jesse Rushlow &amp;lt;jr@geeshoe.com&amp;gt;
Date: Tue Jan 28 05:19:28 2020 -0500

    Initial commit

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I've modified the output above for readability but as you can see, the first (Initial commit) &amp;amp; the third (updated doc) commits were both signed using my GPG key. The second commit (ignore ideas) however was not signed.&lt;/p&gt;




&lt;h3&gt;
  
  
  The fix
&lt;/h3&gt;

&lt;p&gt;As the above scenario doesn't happen often to me, I always seem to forget how to sign previous commits without getting into a git mess. After doing some googling, rebasing hit's me square in the forehead. Duh!&lt;/p&gt;

&lt;p&gt;The key is that we want to begin the rebase at the commit just before the commit which needs to be modified. In this case it will be the initial commit &lt;code&gt;c772d80&lt;/code&gt;. We also want to rebase interactively.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git rebase -i c772d80&lt;/code&gt; will open a text editor that will allow use to tell git which commit we want to modify.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
user@host:~/document$ git rebase -i c772d80

Editor:

pick 95f8587 ignore ideas
pick 4ff30a5 updated doc

# Rebase c772d80..80753f3 onto c772d80 (3 commands)
#
# Commands:
..........

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We are going to change &lt;code&gt;pick&lt;/code&gt; to &lt;code&gt;edit&lt;/code&gt; for &lt;code&gt;pick 95f8587 ignore ideas&lt;/code&gt; within the editor and save as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Editor:

edit 95f8587 ignore ideas
pick 4ff30a5 updated doc

# Rebase c772d80..80753f3 onto c772d80 (3 commands)
#
# Commands:
..........

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Git will then bring you back to the command prompt and halt at the commit that needs editing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
user@host:~/document$ git rebase -i c772d80

Stopped at 95f8587... ignore ideas
You can amend the commit now, with

  git commit --amend '-S'

Once you are satisfied with your changes, run

  git rebase --continue

user@host:~/document$

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now we can sign the commit using &lt;code&gt;git commit --amend --no-edit -S&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--amend&lt;/code&gt; Amend the previous commit.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--no-edit&lt;/code&gt; Use the existing commit message. No need to edit it.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;-S&lt;/code&gt; GPG-sign the commit. If you need to specify the GPG key to use, &lt;code&gt;-S[&amp;lt;keyid&amp;gt;]&lt;/code&gt; is more appropriate.&lt;/p&gt;

&lt;p&gt;After running the above command, git will output something similar to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
user@host:~/document$ git commit --amend --no-edit -S

[detached HEAD c11cc9e] ignore ideas
 Author: Jesse Rushlow &amp;lt;jr@rushlow.dev&amp;gt;
 Date: Tue Jan 28 05:21:15 2020 -0500
 1 file changed, 1 insertion(+)
 create mode 100644 .gitignore

user@host:~/document$

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can now go ahead and finish up the rebase with &lt;code&gt;git rebase --continue&lt;/code&gt; &amp;amp; if all goes well, git will tell you that the rebase was successful. To verify that we signed the commit, &lt;code&gt;git log --show-signature&lt;/code&gt; should now show the GPG signature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
user@host:~/document$ git rebase --continue
Successfully rebased and updated refs/heads/master.

user@host:~/document$ git log --show-signature
...

commit c11cc9e...
gpg: Signature made Tue 28 Jan 2020 05:58:38 AM EST
gpg: using RSA key ...741096D2ADE04CA
gpg: Good signature from "Jesse Rushlow &amp;lt;jr@geeshoe.com&amp;gt;" [ultimate]
Author: Jesse Rushlow &amp;lt;jr@rushlow.dev&amp;gt;
Date: Tue Jan 28 05:21:15 2020 -0500

    ignore ideas

...

user@host:~/document$

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;






&lt;p&gt;You're all set! Happy coding...&lt;/p&gt;

&lt;h2&gt;
  
  
  Word to the wise...
&lt;/h2&gt;

&lt;p&gt;If you have already pushed the unsigned commit upstream to github as I did, care should be taken before using the above described method. As there could be negative consequences.&lt;/p&gt;

&lt;p&gt;First, after performing the rebase, you will more than likely have to force push the branch upstream to github. If this is a feature branch that hasn't been merged / modified by others, forcing the push shouldn't cause any headaches.&lt;/p&gt;

&lt;p&gt;If there have been modifications to the branch / PR upstream, you may want to revert the commit, and just create a new signed commit rather than doing a rebase. If all else fails, you can always let the unsigned commit ride solo as a reminder not to make that mistake again...&lt;/p&gt;

&lt;p&gt;As always comments, rants, suggestions, and constructive criticism are always welcome.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jesse Rushlow &lt;code&gt;jr@rushlow.dev&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>git</category>
      <category>rebase</category>
      <category>gpg</category>
      <category>coding</category>
    </item>
    <item>
      <title>Unit and Functional tests, huh?! Whats the difference?</title>
      <dc:creator>Jesse Rushlow</dc:creator>
      <pubDate>Fri, 17 Jan 2020 23:32:34 +0000</pubDate>
      <link>https://forem.com/jrushlow/unit-and-functional-tests-huh-whats-the-difference-5a2n</link>
      <guid>https://forem.com/jrushlow/unit-and-functional-tests-huh-whats-the-difference-5a2n</guid>
      <description>&lt;h2&gt;
  
  
  How and why you should separate your PHP test suites.
&lt;/h2&gt;

&lt;p&gt;I recently attempted to answer a question on &lt;a href="https://stackoverflow.com/questions/59776521/in-phpunit-how-should-i-test-when-return-values-are-complex-objects"&gt;stack overflow&lt;/a&gt; in regards to PHPUnit testing. Although I feel I wasn't able to convey my answer in a understandable way. So what better way than to try again here...&lt;/p&gt;

&lt;h3&gt;
  
  
  Unit tests vs Functional Tests
&lt;/h3&gt;

&lt;p&gt;A unit test is a test written that checks the behavior of a specific isolated block of code, without depending on the real input from external dependencies. So what are external dependencies? Anything outside of the method/function under test that said method/function relies upon. I.e. a different class method within the codebase, an API response from another server, etc... In unit testing, mocking dependencies allows us to test a code block without having to rely upon it's dependencies.&lt;/p&gt;

&lt;p&gt;A functional test on the other hand is a test written to ensure that all of the code within a code base interacts with each other and its dependencies as expected. When writing functional tests, you don't &lt;em&gt;usually&lt;/em&gt; mock your dependencies. More on this below.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unit Tests
&lt;/h3&gt;

&lt;p&gt;Look at the following two classes. In all, &lt;code&gt;\Store::class&lt;/code&gt; has one dependency,&lt;code&gt;\FruitBasket&lt;/code&gt;, and &lt;code&gt;\FruitBasket&lt;/code&gt; has a dependency of it's own,&lt;code&gt;\Connection::class&lt;/code&gt;, which provides a connection to a "server far away".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class FruitBasket
{
    public $serverFarAway;

    public $fruitArray = ['apple', 'orange']

    public function __construct(\Connection $serverFarAwayConnection)
    {
        $this-serverFarAway = $serverFarAwayConnection
    }

    public function getByType(string $type): string
    {
        $key = in_array($type, $this-&amp;gt;fruitArray);

        if (!$key) {
            return $this-fruit[$key];
        }

        return $this-&amp;gt;getFruitByTypeFromServerFarAway($type);
    }

    protected function getFruitByTypeFromServerFarAway(string $type): string
    {
        return $this-serverFarAway-&amp;gt;getFruit($type);
    }
}

class Store
{
    public $basket;

    public function __construct(\FruitBasket $basket)
    {
        $this-&amp;gt;basket = $basket;
    }

    public function getFruit(string $typeOfFruit): string
    {
        return $this-basket-&amp;gt;getByType($typeOfFruit);
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To unit test &lt;code&gt;\Store::class&lt;/code&gt;, we must mock &lt;code&gt;\FruitBasket&lt;/code&gt; before testing the&lt;code&gt;\Store::getFruit()&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//UnitTest.php

use PHPUnit\Framework\TestCase;

class UnitTest extends TestCase
{
    public function testGetFruitReturnsOrangeWhenOrangeIsTheParam(): void
    {
        $mockBasket = $this-createMock(\FruitBasket::class);
        $mockBasket-&amp;gt;expects($this-once())
            -&amp;gt;method('getByType')
            -&amp;gt;with('orange')
            -&amp;gt;willReturn('Orange')
        ;

        $store = new Store($mockBasket);
        $result = $store-&amp;gt;getFruit('orange');

        self::assertSame('Orange', $result);
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The above test is actually performing 2 assertions. The first, &lt;code&gt;self::assertSame&lt;/code&gt;is obvious. We are testing that &lt;code&gt;$store-&amp;gt;getFruit()&lt;/code&gt; returns the result from&lt;code&gt;\FruitBasket::getByType()&lt;/code&gt;. The 2nd assertion is that &lt;code&gt;\FruitBasket::getByType()&lt;/code&gt;is actually being called by &lt;code&gt;\Store::getFruit()&lt;/code&gt; exactly 1 time. We are also ensuring that when we call &lt;code&gt;\Store::getFruit('orange')&lt;/code&gt;, our 'orange' parameter is being passed to &lt;code&gt;\FruitBasket::getByType()&lt;/code&gt;. We are accomplishing this without actually using a real &lt;code&gt;\FruitBasket&lt;/code&gt; object in the test.&lt;/p&gt;

&lt;p&gt;The next unit tests we would write would be for &lt;code&gt;\FruitBasket::class&lt;/code&gt;;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//UnitTest2.php

use PHPUnit\Framework\TestCase;

class UnitTest2 extends TestCase
{
    public $mockConnection;

    protected function setUp(): void
    {
        $this-mockConnection = $this-createMock(\Connection::class);
    }

    public function testGetByTypeReturnsFruitInFruitAway(): void
    {
        $expectedResult = 'apple';

        $basket = new \FruitBasket($this-mockConnection);

        $result = $basket-&amp;gt;getByType('apple');

        self::assertSame($expectedResult, $result);
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We are essentially doing the same as before, expect this time we are using the inherited&lt;code&gt;TestCase::setUp()&lt;/code&gt; method. &lt;code&gt;setUp()&lt;/code&gt; allows us to create a fresh mock of the&lt;code&gt;\Connection::class&lt;/code&gt; before each test is run. Of course we need the &lt;code&gt;\Connection::class&lt;/code&gt;to create a new &lt;code&gt;\FruitBasket::class&lt;/code&gt; instance.&lt;/p&gt;

&lt;p&gt;Now we could write more tests for the different edge cases that are possible for&lt;code&gt;\FruitBasket&lt;/code&gt;. We could also write assertions for the &lt;code&gt;\Connection:class&lt;/code&gt; mock to ensure that if a fruit is not found in &lt;code&gt;$fruitArray&lt;/code&gt;,&lt;code&gt;\Connection::getFruitByTypeFromServerFarAway()&lt;/code&gt; is called with the &lt;code&gt;$type&lt;/code&gt;parameter. You would write those assertions just as I did in the previous example.&lt;/p&gt;

&lt;h3&gt;
  
  
  Functional Tests
&lt;/h3&gt;

&lt;p&gt;After we have written our unit tests to ensure each individual method performs as expected, it's time to test if both classes work together as expected. There are 2 ways to go about this. The first, in true functional test form, would be to use a real &lt;code&gt;\Connection::class&lt;/code&gt; to connect us to a "server far way."&lt;/p&gt;

&lt;p&gt;The upside to this, is we don't have to write mocks out for &lt;code&gt;\Connection::class&lt;/code&gt;and we will be absolutely sure that all the code act's as expected in a perfect world. However, for every upside there's a downside. First, if &lt;code&gt;\Connection::class&lt;/code&gt;is providing us a connection to a MySQL server or API connection that we can't control, which is often the case in the real world; We wouldn't want to be hitting those resources over and over again with our test suite. Think rate limiting for API's.&lt;/p&gt;

&lt;p&gt;Second, who knows what data exists on the "server far away" servers. What if 6 months from now, there were no more bananas left, and we needed to test if we called&lt;code&gt;\Store::getFruit('banana)&lt;/code&gt;, &lt;code&gt;\FruitBasket::getFruitByTypeFromServerFarAway&lt;/code&gt; returned us a banana in our functional test.&lt;/p&gt;

&lt;p&gt;How do we overcome this? My approach is to use a modified version of Functional Testing. If possible, I will replicate the external resource. I.e. create a MySQL docker container that has bananas in a table. Or, just use a mock &lt;code&gt;\Connection::class&lt;/code&gt;object for all but a few of my functional test methods. You could also mock&lt;code&gt;\Connection::class&lt;/code&gt; for all of your Functional tests and utilize a real connection in a separate Functional Test suite or even use a real connection only in your acceptance tests. How you do it all depends on your code base and what external dependencies you are relying on. There is no single "right way" to do it.&lt;/p&gt;

&lt;p&gt;But for this example, I'm going to mock our &lt;code&gt;\Connection::class&lt;/code&gt; in the functional tests because &lt;code&gt;\Connection::class&lt;/code&gt; provides a connection to a server which I don't control and has rate limits.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//FunctionalTest.php

use PHPUnit\Framework\TestCase;

class FunctionalTest extends TestCase
{
    public $mockConnection;

    protected function setUp(): void
    {
        $this-mockConnection = $this-createMock(\Connection::class);
    }

    public function testGetFruitReturnsFruit(): void
    {
        $fruitBasket = new \FruitBasket($this-mockConnection);
        $store = new \Store($fruitBasket);

        $result = $store-&amp;gt;getFruit('apple');

        self::assertSame('apple', $result);
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In the example above, we are testing the &lt;code&gt;\Store::getFruit()&lt;/code&gt; and &lt;code&gt;\FruitBasket::getByType()&lt;/code&gt;interact with each other as expected. But what happens when &lt;code&gt;\FruitBasked-&amp;gt;$fruitArray&lt;/code&gt;doesn't contain the desired fruit?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//FunctionTest.php

use PHPUnit\Framework\TestCase;

class FunctionalTest extends TestCase
{
    public $mockConnection;

    protected function setUp(): void
    {
        $this-mockConnection = $this-createMock(\Connection::class);
    }

    public function testGetFruitReturnsFruit(): void
    {
        ....
    }

    public function testGetFruitReturnsBananas(): void
    {
        $this-mockConnection-&amp;gt;method('getFruit')
            -&amp;gt;willReturn('Banana')
            -&amp;gt;with('banana')

        $fruitBasket = new \FruitBasket($this-mockConnection);
        $store = new \Store($fruitBasket);

        $result = $store-&amp;gt;getFruit('banana');
        self::assertSame('Banana', $result);
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We are still using a mock connection, but we a doing it while running a functional test. As &lt;code&gt;\Store::class&lt;/code&gt; is utilizing a real &lt;code&gt;\FruitBasket::class&lt;/code&gt; instance within the test.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final thoughts
&lt;/h3&gt;

&lt;p&gt;The key take away is unit tests should not interact with any real dependencies where as functional tests can and should where possible.&lt;/p&gt;

&lt;p&gt;A few may argue that you shouldn't use mocks at all in functional tests. And that is true to a point. But in the examples above, &lt;code&gt;\Connection::class&lt;/code&gt; is an external dependency that should be tested in it's own code base. And as such, mocking it is safe in this use case. As the developer, you should pick external dependencies that are thoroughly tested and maintained regularly before implementing them in your own code base.&lt;/p&gt;

&lt;p&gt;I hope this helps. As always, comments, rants, suggestions, and constructive criticism is always welcome.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jesse Rushlow &lt;code&gt;jr (at) rushlow (dot) dev&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>php</category>
      <category>testing</category>
      <category>phpunit</category>
    </item>
    <item>
      <title>Overflow reality check</title>
      <dc:creator>Jesse Rushlow</dc:creator>
      <pubDate>Thu, 09 Jan 2020 04:09:35 +0000</pubDate>
      <link>https://forem.com/jrushlow/overflow-reality-check-1dl8</link>
      <guid>https://forem.com/jrushlow/overflow-reality-check-1dl8</guid>
      <description>&lt;h2&gt;
  
  
  &lt;em&gt;The misadventures of a compound problem involving css, cache, and cross-browser support.&lt;/em&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  TL;DR
&lt;/h3&gt;




&lt;p&gt;Overcome overflow with long strings in a &lt;code&gt;pre&lt;/code&gt; tag with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pre {
  white-space: pre-wrap;
  white-space: -moz-pre-wrap;
  white-space: -o-pre-wrap;
  overflow-wrap: break-word;
  word-wrap: break-word;
  word-break: break-word;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;




&lt;p&gt;After recording, editing, writing, and finally posting my article on &lt;a href="https://dev.to/jrushlow/php-workspace-container-part-1-14nf"&gt;how to create a Docker container to initiate PHP projects&lt;/a&gt;, I was pretty content with the result. I'm not a hollywood video producer or even an expert at creating tutorials of any kind. But I do just so happen to be pretty good at writing code, or so I thought...&lt;/p&gt;

&lt;p&gt;Once I published the article to my site, &lt;a href="https://rushlow.dev"&gt;rushlow.dev&lt;/a&gt;, I had to make a few tweak's to the final result, mainly to the articles CSS properties. Woohoo, all looks good! WRONG, a week after publishing I just so happened to pull up the article on my phone and realized something was off.&lt;/p&gt;

&lt;p&gt;A few code snippets that I had enclosed in &lt;code&gt;&amp;lt;pre&amp;gt;...&amp;lt;/pre&amp;gt;&lt;/code&gt; were overflowing their container. This in turn caused my responsive design to become un-responsive; scroll bars appeared out of no where and the entire article was hard to read on my iPhone. So, as any developer in my shoes would do, I fired up my IDE and began toying with the code base to fix the problem. After a few minutes I discovered I had forgot to set &lt;code&gt;white-space: pre-wrap;&lt;/code&gt; on the &lt;code&gt;pre&lt;/code&gt; CSS property. Phew... Problem solved!&lt;/p&gt;

&lt;p&gt;Prior to pushing my code, I had fired up Firefox &amp;amp; Chrome on my dev machine to make sure everything looked right. So far so good, using the built in dev tools, I played around with the viewport size and all is well. I then ran my tests, inspected the code, and merged the fix into production. Fire up Firefox on my iPhone again, and the problem is still there. A few explitives later, I found myself fussing with CSS once again.&lt;/p&gt;

&lt;p&gt;To shorten this up a bit, one would think the iPhone version and the desktop version of Firefox, Chrome, etc.. would produce the same result regardless of the device you are using the respective app on. Nope! When I did my final check of the article while in staging, both in Firefox and Chrome, the overflow had disappeared. However while viewing the same code base in the same staging environment with the same browsers but on my iOS device, the problem kept reappearing.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;




&lt;p&gt;Part of the solution was to kick my self in the butt for breaking one of the golden rules while developing, especially anything related to CSS; disable any cache that may affect the desired result. Ahhhhhh, that's better. Now part of my problem has been solved. What I see on my iPhone is what I see on my desktop. GRRRR nope, nope, the result is improved but slightly different.&lt;/p&gt;

&lt;p&gt;My &lt;code&gt;pre&lt;/code&gt; tags are being wrapped accordingly but a few lines are still busting the container. It just so happens that the lines that are busting the container are long strings. &lt;code&gt;white-space: pre-wrap;&lt;/code&gt; breaks a line at newline characters,&lt;code&gt;&amp;lt;br&amp;gt;&lt;/code&gt;, and "as necessary to fill line boxes." What &lt;code&gt;white-space: pre-wrap;&lt;/code&gt;doesn't do is break long strings to preserve width constraints. To do that you must use &lt;code&gt;word-wrap: break-word;&lt;/code&gt;, which is an alias for&lt;code&gt;overflow-wrap: break-word;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;overflow-wrap: break-word;&lt;/code&gt; allows for a word to be broken at any arbitrary point and does not take into account soft wrap opportunities introduced by breaking up a word.&lt;/p&gt;

&lt;p&gt;The last part of the fix is to account for browser specific styles. To do that, I added:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pre {
    white-space: -moz-pre-wrap;
    white-space: -o-pre-wrap;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Depending on your requirements, you can also add hyphens to word breaks with&lt;code&gt;hyphens: auto&lt;/code&gt;. As my blog is mostly of a technical nature, auto hyphens would create more confusion in most situations where I utilize &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; tags. For instance, in citing a command or url, if one were to copy and paste a string that was "auto hyphened", the user would immediatly say something is broken. As&lt;code&gt;www.google.com&lt;/code&gt; is obviously not the same as &lt;code&gt;www.go-ogle.com&lt;/code&gt;. Take this into consideration before applying CSS based auto hyphens.&lt;/p&gt;

&lt;p&gt;My final thought on all of this is that to keep in mind a browser on one platform, Firefox/Chrome on Debian, will not behave the same on another platform. I.e. Firefox/ Chrome on iOS. Also, regardless of how long you've been writing code, always remember KISS. Keep it simple stupid! I often have to remind myself that the hardest of problems can be caused by the most simplistic solution that is right in front of your face. I.e. checking "disable cache" in a browser...&lt;/p&gt;




&lt;p&gt;For more details on any of the referenced tags, checkout Chris Coyier's article at &lt;a href="https://css-tricks.com/snippets/css/prevent-long-urls-from-breaking-out-of-container/"&gt;css-tricks&lt;/a&gt; &amp;amp; of course the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS"&gt;MDN web docs&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>css</category>
      <category>cache</category>
      <category>frontend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>PHP Workspace Container Part 1</title>
      <dc:creator>Jesse Rushlow</dc:creator>
      <pubDate>Mon, 30 Dec 2019 23:58:10 +0000</pubDate>
      <link>https://forem.com/jrushlow/php-workspace-container-part-1-14nf</link>
      <guid>https://forem.com/jrushlow/php-workspace-container-part-1-14nf</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/zyHWYpVP6Gs"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  TL;DR;
&lt;/h3&gt;

&lt;p&gt;Create a docker container to provide PHP's CLI, Composer, Git, Node &amp;amp; Yarn that is not project specific and without the need to have any of the aforementioned tools installed on the host.&lt;/p&gt;

&lt;p&gt;I'll be demonstrating how to accomplish this using Debian Buster as the host with docker and docker-compose already installed. &lt;/p&gt;

&lt;p&gt;The source code for this project is available on &lt;a href="https://github.com/jrushlow/docker-php-workspace"&gt;GitHub&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;I use a directory structure on my host that allows me to store all of my PHP, Javascript, Python, etc. in separate folders organized by the project language. This allows me to have one workspace container per language. I.e.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- ~/develop/php
    - /symfony-app-1
    - /symfony-app-2
- ~/develop/python
    - /python-app
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Creating our container&lt;/p&gt;




&lt;p&gt;First we can go ahead and create our directory structure as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ~/develop/php
mkdir workspace
touch .bash_aliases Dockerfile Makefile

- ~/php
    - .bash_aliases
    - Dockerfile
    - Makefile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, we'll define our docker image in the &lt;code&gt;Dockerfile&lt;/code&gt; as follow's:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Dockerfile

FROM php:7.4-cli-buster

RUN apt-get update &amp;amp;&amp;amp; apt-get install -yqq \
    libzip-dev \
    zip \
    gnupg \
    git

# Install node and Yarn in workspace container
RUN curl -sL https://deb.nodesource.com/setup_12.x | bash &amp;amp;&amp;amp; \
    curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add &amp;amp;&amp;amp; \
    echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list

RUN apt-get update &amp;amp;&amp;amp; apt-get install -yqq \
    nodejs \
    yarn

# Install composer &amp;amp; make compose global
RUN curl -s https://getcomposer.org/installer | php &amp;amp;&amp;amp; \
    mv composer.phar /usr/local/bin/composer

# Create a regular user account to work from
RUN set -xe; \
    groupadd -g 1000 developer &amp;amp;&amp;amp; \
    useradd -u 1000 -g developer -m developer &amp;amp;&amp;amp; \
    usermod -p "*" developer -s /bin/bash

# Copy bash aliases defined on host to container
COPY .bash_aliases /home/developer/.bash_aliases

# Cleanup
RUN apt-get clean &amp;amp;&amp;amp; \
    rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

# Set which account to use
USER developer

# Set working dir for container
WORKDIR /var/develop
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, add any bash aliases that you want present within the workspace to &lt;code&gt;.bash_aliases&lt;/code&gt; such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// .bash_aliases
alias la="ls -lah"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The above can be omitted if you prefer not to use any aliases, just remember to remove the &lt;code&gt;COPY .bash_aliases /home/developer/.bash_aliases&lt;/code&gt; from the Dockerfile.&lt;/p&gt;

&lt;p&gt;Create make targets&lt;/p&gt;




&lt;p&gt;We could go ahead and fire up our container now without any issues using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$&amp;gt; cd php/workspace
php/workspace:$&amp;gt; docker build . -t workspace:latest

....
Successfully built f6f89d2035c7
Successfully tagged workspace:latest

php/workspace:$&amp;gt; docker run -ti --rm --mount type=bind,src=/php,dst=/var/develop \
workspace:latest /bin/bash

developer@f6f89d2035c7:/var/develop$&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;But that's a lot of typing every time we need to enter the workspace container. We could use bash aliases to make this easier, but that can get unwieldy if you manage a lot of docker containers. I have chosen to use make to simplify my docker life. &lt;/p&gt;

&lt;p&gt;Edit your &lt;code&gt;Makefile&lt;/code&gt; as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Makefile

.PHONY: build
build: ## Build docker workspace image
   docker build . -t workspace:latest

.PHONY: workspace
workspace: ## Launch workspace container bash shell
   docker run -ti --rm --mount type=bind,src=/path/to/develop/php,dst=/var/develop workspace:latest /bin/bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now all I have to do is call the make target's to build and launch the container like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php/workspace:$&amp;gt; make build
docker build . -t workspace:latest
Successfully built f6f89d2035c7
Successfully tagged workspace:latest

php/workspace:$&amp;gt; make workspace
docker run -ti --rm --mount type=bind,src=/path/to/develop/php,dst=/var/develop workspace:latest /bin/bash

developer@f6f89d2035c7:/var/develop$&amp;gt; WOOHOOO!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The best part about using make targets is portability. If you are managing several project's that each have their own docker images / containers, you can reuse the same makefile, with a little tweaking, across all of your projects. And best of all, it can be committed to your Git repo for others to use as well.&lt;/p&gt;

&lt;p&gt;There are differences in how make works on linux based systems compared to Windows environments, but the principles are all the same.&lt;/p&gt;




&lt;p&gt;Stay tuned for future video's in this series...&lt;/p&gt;

</description>
      <category>php</category>
      <category>docker</category>
    </item>
    <item>
      <title>PHP 7.4 Typed Properties BC Problems</title>
      <dc:creator>Jesse Rushlow</dc:creator>
      <pubDate>Fri, 27 Dec 2019 02:13:51 +0000</pubDate>
      <link>https://forem.com/jrushlow/php-7-4-typed-properties-bc-problems-22hh</link>
      <guid>https://forem.com/jrushlow/php-7-4-typed-properties-bc-problems-22hh</guid>
      <description>&lt;p&gt;Prior to PHP 7.4, declaring property scalar types was done with DocBlocks as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/ **@var int|null** /
public $id;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With typed properties introduced in PHP 7.4, the scalar type can now be set like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public ?int $id;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is awesome, it cuts down on excessive boilerplate and the PHP interpreter will not allow an invalid value to be set on the property.&lt;/p&gt;

&lt;p&gt;But, there are a couple caveats to be aware of...&lt;/p&gt;

&lt;p&gt;Without setting a property type, one would be able to have a class property such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//class.php

&amp;lt;?php
class MyClass {

    / **@var int|null** /
    public $id;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And then call the property without any problems like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//test.php

&amp;lt;?php
require('class.php');

$object = new MyClass;
$var = $object-&amp;gt;id;

var_dump($var);

$:&amp;gt; php -f test.php
NULL
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;However if you declare the property type and then attempt to access that type as above, you'll get a FatalError. I.e.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//test.php

&amp;lt;?php
class MyClass {

    public ?int $id;
}

$object = new MyClass;
$var = $object-&amp;gt;int;

echo $var;

$:&amp;gt; php -f test.php
Fatal error: Uncaught Error: Typed property MyClass::$id must not be accessed before initialization...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To overcome this, you must set the value of &lt;code&gt;$id&lt;/code&gt; before attempting to access it.  This can be accomplished in a number of ways.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class MyClass {

    public ?int $id = null;
}

class MyClass {

    public ?int $id;

    public function __construct() {
        $this-&amp;gt;id = null;
    }
}

class MyClass {

    public ?int $id;

    public function setId(?int $id) {
        $this-&amp;gt;id = $id;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Using any of the above means of setting &lt;code&gt;$id&lt;/code&gt; before accessing the value of &lt;code&gt;$id&lt;/code&gt; would result in the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//class.php
&amp;lt;?php
class MyClass {

    public ?int $id = null;
}

$object = new MyClass;

$var = $object-&amp;gt;id;

var_dump($var;)

$:&amp;gt; php -f class.php
NULL
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Of course if you are using setter's to set the value of &lt;code&gt;$id&lt;/code&gt;, you must call the setter method before accessing the property.&lt;/p&gt;

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