Todd Eidson's Programming Bloghttps://eidson.info
Programming Blogen-usCatching Mail with MailCatcherhttps://eidson.info/post/catching-mail-with-mailcatcher
<p><img src="/img/mail.webp" alt="" title="mailboxes" /></p>
<h1>Catching Mail with MailCatcher</h1>
<h2>MailCatcher</h2>
<p><a href="https://mailcatcher.me/">MailCatcher</a> is a powerful and easy to use Ruby gem that acts as an SMTP server that allows you to inspect emails that your application is sending out in your dev environment.</p>
<h3>Installation</h3>
<p>Installation is pretty simple, these are the commands that I used on my Fedora 29 install to get it up and running. If Ruby is already installed on your machine, or if you've already installed other Ruby gems, you may not need the first few lines.</p>
<pre><code class="language-bash">sudo dnf install ruby
sudo dnf group install &quot;C Development Tools and Libraries&quot;
sudo dnf install ruby-devel zlib-devel
# Redhat-rpm-config and libsqlite3x-devel are the mailcatcher specific requirements
sudo dnf install redhat-rpm-config libsqlite3x-devel
gem install mailcatcher
</code></pre>
<p>After everything installs properly, from a terminal run MailCatcher.</p>
<pre><code class="language-bash">mailcatcher
</code></pre>
<p>MailCatcher has options that you can pass it if you need to change the SMTP port or the port the web front end uses, these can be viewed by running <code>mailcatcher --help</code>.</p>
<p>Now that MailCatcher is up and running, we're ready to send it some e-mail.</p>
<h2>Symfony</h2>
<p>The default <code>MAILER_URL</code> is NULL in a Symfony project, which is rational setting that ensures that you aren't sending out emails while running a project in the dev environment (which I've done, on more than one occasion). However, there are occasions when you want to verify that an e-mail is being sent or you want to inspect the contents of that email. Symfony, of course, does provide <a href="https://symfony.com/doc/current/email/dev_environment.html">ways</a> through the Web Debug Toolbar to view the contents of sent e-mail and to override the intended recipient, so you aren't spamming users with dev emails (but you have to check the header if you want to see who the intended recipient was). However, I find that using MailCatcher has a more developer friendly UI and requires less configuration.</p>
<p>In your Symfony <code>.env</code> file change the <code>MAILER_URL</code> to point to the instance of MailCatcher.</p>
<pre><code class="language-bash"># .env file
MAILER_URL=smtp://localhost:1025
</code></pre>
<p>Now all that is left to do is to point a browser to <a href="http://127.0.0.1:1080/">http://127.0.0.1:1080/</a> to see any emails that are sent from your Symfony project.</p>
<p>Of course, one other benefit of using MailCatcher over the built-in Symfony tools for catching dev emails is that you aren't limited to using this for just Symfony projects. You can drop this in anywhere that has a configurable SMTP url setting.</p>
Sun, 31 Mar 2019 00:00:00 UTCUseshttps://eidson.info/post/uses
<p><img src="/img/IMG_1784.jpg" alt="" title="View" /></p>
<h1>Uses</h1>
<p>Inspired years ago by <a href="https://www.hanselman.com/blog/ScottHanselmans2014UltimateDeveloperAndPowerUsersToolListForWindows.aspxi">Scott Hanselman's tool list</a> and more recently by <a href="https://wesbos.com/uses/">Wes Bos' uses</a> and prodded into action so I could make a pull request to the <a href="https://github.com/wesbos/awesome-uses">awesome-uses</a> repo by Wes Bos, here is a list of the tools that I use on a daily basis:</p>
<h2>Operating System</h2>
<ul>
<li>
<a href="https://getfedora.org/">Fedora</a> - currently using version 29. I've been using different flavors of Linux off and on since 2009, but after switching to Fedora (26?) in November of 2017 from Win10 both at work and at home, I haven't looked back since...</li>
</ul>
<h2>IDE's/Code Editors</h2>
<ul>
<li>
<p><a href="https://www.jetbrains.com/phpstorm/">PhpStorm</a> - This is my go-to workhorse IDE - amazing to work in, not a single feature that I can think of that is missing. In fact, I have ALL of the JetBrain's IDE's on my work machine thanks to their Toolbox Subscription model, absolute best bang for your buck, IMO.</p>
</li>
<li>
<p><a href="https://code.visualstudio.com/">Visual Studio Code</a> - I pull this one out when I don't need all the features of PhpStorm and want to use something a little lighter.</p>
</li>
<li>
<p><a href="https://www.sublimetext.com/3">Sublime Text 3</a> - Because a carpenter needs to have more than one type of hammer in their bag, and be proficient in using them. This is another great lightweight code editor that still gets lots of use.</p>
</li>
<li>
<p><a href="https://www.eclipse.org/birt/about/designer.php">Eclipse BIRT Report Designer</a> - I use this one reluctantly at work when I need to write a database report.</p>
</li>
</ul>
<h2>Terminals</h2>
<ul>
<li>
<p><a href="https://github.com/Guake/guake">Guake</a> - I love the f12 hotkey to bring this up, so fast to fire off a quick terminal command</p>
</li>
<li>
<p><a href="https://gnometerminator.blogspot.com/p/introduction.html">Terminator</a> - If I want a more persistent terminal docked beside another window, I'll fire up Terminator</p>
</li>
</ul>
<h2>File Comparator</h2>
<ul>
<li>
<p><a href="https://www.scootersoftware.com/">Beyond Compare</a> - Nothing beats the features of Beyond Compare for file/directory comparison.</p>
</li>
<li>
<p><a href="http://meldmerge.org/">meld</a> - Is a great free alternative</p>
</li>
</ul>
<h2>SQL Tools</h2>
<ul>
<li>
<p><a href="https://www.jetbrains.com/datagrip/">DataGrip</a> - Another great tool from Jetbrains. I'm still finding a new neat feature almost daily.</p>
</li>
<li>
<p><a href="https://heidisql.com">HeidiSQL</a> - I use HeidiSQL via wine to address a couple areas that DataGrip is lacking in:</p>
<ul>
<li>
<p>Copying tables with or without data to a new database - I copy a lot of tables from prod to dev to develop with real data, or sometimes, I'll copy a table from dev/test to prod when I am implementing a new feature. DataGrip has implemented this recently, but it is still no where as nice as using HeidiSQL</p>
</li>
<li>
<p>Creating VIEWs - this is another area where HeidiSQL beats DataGrip hands down</p>
</li>
</ul>
</li>
</ul>
<h2>Notes</h2>
<ul>
<li>
<a href="https://www.notion.so/">notion</a> - I'd tried lots of other apps to keep notes in and nothing comes close to the power of notion. I've only scratched the surface of its flexibility, but it is still amazingly useful even only using the bare-bones features.</li>
</ul>
<h2>Hardware</h2>
<ul>
<li>
<p>Razer Black Widow Ultimate 2013 Keyboard - I wanted a mechanical keyboard with lighting and this one filled the bill. I liked it so much that I ran out and bought a second one for work after only using it at home for a week. They've served me well for almost 6 years now, but I am tempted by the sexiness of the <a href="http://www.wasdkeyboards.com/index.php/products/code-keyboard.html">wasd CODE keyboard</a>. I might pick up one as a present to myself someday soon.</p>
</li>
<li>
<p><a href="https://www.amazon.com/gp/product/B06XWDJZLF/ref=ppx_yo_dt_b_asin_title_o08_s00?ie=UTF8&amp;psc=1">Sleekform Ergonomic Adjustable Office Desk Chair</a> - I lost my Herman Miller Aeron chair in a break up, so I replaced it with this much more affordable knock off from Amazon. It's just as comfortable and durable as the Aeron, and assembly was much easier.</p>
</li>
</ul>
<img src="/img/IMG_1788.jpg" width="50%">
<h2>Music</h2>
<p>I couldn't last a day in my office or home office without some music...</p>
<ul>
<li>
<p>Thorens TD-166 MkII Turntable - They made everything better in the 1970s (including me) - This was my Father's Day present to myself several years ago.</p>
</li>
<li>
<p>Kenwood KA-8006 Solid State Stereo Integrated Amplifier - Just look at all those real knobs and switches... and it sounds great, too!</p>
</li>
<li>
<p>KLH AV-44 Speakers - The only part of my system made this century, but I'll give them a pass. They still can keep up with my vintage gear.</p>
</li>
</ul>
<img src="/img/IMG_1787.jpg" width="40%" style="float: left; margin: 30px;">
<img src="/img/IMG_1786.jpg" width="40%" style="margin: 30px;">
<br>
Sat, 23 Mar 2019 00:00:00 UTCUsing Conventional Commit Messages - Globallyhttps://eidson.info/post/using-conventional-commit-messages-globally
<p><img src="/img/git-logo.png" alt="" title="git logo" /></p>
<h1>Automating Conventional Commit Messages - Globally</h1>
<p>I am constantly on the lookout for ways to better myself as a developer. This includes not only getting better at the actual art of coding but also improving the processes of coding and finding ways to streamline and/or automate these processes. One of the areas that I had already (mostly) improved on is writing useful commit messages, so my <code>git log</code> doesn't end up looking like this XKCD comic:</p>
<p><img src="https://imgs.xkcd.com/comics/git_commit.png" alt="" title="XKCD Commit Comic" /></p>
<p>One bad habit that is easy to fall into as a solo developer (especially under a time constraint) is to rationalize ignoring or delaying proper documentation since you're the only one working in the codebase it is easy to think that documentation is unimportant. And it is. Until it isn't - and then it is <em>really</em> important.</p>
<p>So that is one area that I am constantly trying to improve in. A git commit message is an oft-overlooked and undervalued form of documentation, so how can we improve here? I had already been, for the most part, following <a href="https://chris.beams.io/posts/git-commit/#seven-rules">The seven rules of a great Git commit message</a>. They made sense and were easy enough to implement, and almost got me to where I wanted to be as far as git commit messages were concerned.</p>
<p>However, I was recently made aware of the <a href="https://www.conventionalcommits.org/">Conventional Commits</a> standard published by the Angular Team thanks to the <a href="https://dev.to/maxpou/enhance-your-git-log-with-conventional-commits-3ea4">Enhance your git log with conventional commits</a> post on <a href="https://dev.to">dev.to</a>. I really liked the article and the standard so I bookmarked it for a more thorough reading. It was a couple of days later when I went back to the post and saw the following <a href="https://dev.to/joelnet/comment/9be2">comment</a> that really got my wheels spinning:</p>
<blockquote>
<p><a href="https://dev.to/joelnet">JavaScript Joel</a></p>
<p>I have added husky + commitizen + commitlint to our projects and it has been great.</p>
<p>Some benefits include an auto-generated change log. auto-incrementing semantic versioning. and increased visibility for breaking changes.</p>
<p>I would recommend it for every project.</p>
<p>Because we are using gitlab, we are using these packages semantic-release-gitlab and npm-publish-git-tag.</p>
</blockquote>
<p>So I got to googling and found the <a href="https://dev.bleacherreport.com/how-we-use-commitizen-to-clean-up-commit-messages-a16790dcd2fd">How We Use Commitizen to Clean Up Commit Messages</a> post that I used for a starting point on implementing and enforcing conventional commit messages.</p>
<p>The only problem was that the vast majority of my projects are PHP projects, and these are all npm packages. As much as I wanted to add this to my workflow, I wasn't keen on the idea of adding a <code>package.json</code> file to each project and adding unnecessary complexity to my dev process. So I went about discovering if these tools could be added globally so they could be added to my ~30 projects without configuring them individually for each project.</p>
<h2>The Tools</h2>
<p>There were three tools that I had to configure:</p>
<ul>
<li>
<a href="https://github.com/commitizen/cz-cli">commitizen</a>- Help write the conventional commit message</li>
<li>
<a href="https://github.com/conventional-changelog/commitlint">commitlint</a> - Determine if the commit message is properly formatted</li>
<li>
<a href="https://eidson.info/post/global-hooks-with-git">git global hooks</a> - Fail the commit if the commit message is not properly formatted</li>
</ul>
<h3>Commitizen</h3>
<p><a href="https://github.com/commitizen/cz-cli">commitizen</a> is a handy little command line utility that provides prompts and hints for filling out each section for a conventional commit message.</p>
<p>The first step is to install it using npm:</p>
<pre><code class="language-bash">npm install -g commitizen
</code></pre>
<p>Install your preferred commitizen adapter globally, for example cz-conventional-changelog</p>
<pre><code class="language-bash">npm install -g cz-conventional-changelog
</code></pre>
<p>Create a .czrc file in your home directory, with path referring to the preferred, globally installed, commitizen adapter</p>
<pre><code class="language-bash">echo '{ &quot;path&quot;: &quot;cz-conventional-changelog&quot; }' &gt; ~/.czrc
</code></pre>
<p>After commitizen has been installed, instead of making a commit with <code>git commit</code> you make a commit with:</p>
<pre><code class="language-bash">git cz
</code></pre>
<p>This launches commitzen and you'll be prompted to first select the type of commit you are making:</p>
<img src="/img/commitizen_1.png" width="100%">
<br>
<p>After the type of commit is selected, you'll be prompted to fill out the subject, body, breaking changes, and open issues sections:</p>
<img src="/img/commitizen_2.png" width="100%">
<br>
<div class="card">
<h5 class="card-header">Pro-tip:</h5>
<div class="card-body">
For the body (`Provide a longer description of the change:`)
<br>
If you want to add newlines you can add them with the `\n` newline character.
<pre>
<code class="language-bash hijs">
Does a thing that is important\n\nBy doing\n-Thing 1\n-Thing 2
</code>
</pre>
The dashes create a bullet list.<br>
<br>
Yes, this is an ugly work around, but the only way that I found that works, and not a deal breaker, for me.
</div>
</div>
Now that commitizen is installed and working, we can move on to the next step.
<h2>Commitlint</h2>
<p><a href="https://github.com/conventional-changelog/commitlint">commitlint</a> is a tool that will lint your commit message and let you know if it adheres to whatever standard you've chosen.</p>
<p>Global installation is as easy as commitizen, but it is not explained in the readme. I had to dig around in the github issues to find an example. I plan on making a pull request to remedy this, but here are the steps:</p>
<p>Install the cli utility and the configuration you wish to apply:</p>
<pre><code class="language-bash">npm install -g @commitlint/cli @commitlint/config-conventional
</code></pre>
<p>Create a global config file:</p>
<pre><code class="language-bash">echo &quot;module.exports = {extends: ['@commitlint/config-conventional']}&quot; &gt; ~/commitlint.config.js
</code></pre>
<p>That is all there to it. You can test that it is installed and working by running the following command:</p>
<pre><code class="language-bash">echo 'should fail' | commitlint
</code></pre>
<p>And to see a passing message you can try:</p>
<pre><code class="language-bash">echo &quot;fix(server): send cors headers&quot; | commitlint
</code></pre>
<p>Now we're ready to tie it all together...</p>
<h2>git hook</h2>
<p>commitlint in and of itself does not really do much until it is placed into a git hook. It is from inside this hook that we can fail the commit if the message does not follow the standard.</p>
<p>Like the earlier npm packages, I wanted this applied to all of my projects, without configuring a git hook for each individual project. If you are unfamiliar with using git hooks globally, you can check out my previous post on <a href="https://eidson.info/post/global-hooks-with-git">git global hooks</a>.</p>
<p>If you've got global git hooks configured already, you can add a file as <code>/path/to/global/hooks/commit-msg</code>. I use the fish shell for my scripting, but the bash shouldn't look too much different. The line <code>commitlint &lt; $argv[1]</code> does the work, I think bash would be <code>commitlint &lt; $1</code></p>
<pre><code class="language-bash">#! /usr/bin/fish
# run any local commit-msg hook first
if test -e ./.git/hooks/commit-msg
sh ./.git/hooks/commit-msg
end
commitlint &lt; $argv[1]
exit $status
</code></pre>
<h2>In Conclusion</h2>
<p>So there you have it, three easy steps to set up a conventional commit message workflow. This is most useful if you can get in the habit of making <a href="https://seesparkbox.com/foundry/atomic_commits_with_git">atomic commits</a>. You can see the real beauty of this after making a few commits and then running <code>git log --one-line</code>. Give it a shot and see what you think!</p>
Sun, 17 Mar 2019 00:00:00 UTCUnit Testing PHP Dates and Times with Carbonhttps://eidson.info/post/unit-testing-dates-and-times-with-carbon
<p><img src="/img/php.png" alt="php logo" title="php logo" /></p>
<h1>Unit Testing Dates and Times with Carbon</h1>
<p>One area of my codebase at work that I had problems sufficiently testing were instances in my code base that had time based logic to them. Since I work in the manufacturing sector, lots of logic relies on knowing what the current, last, or next shift is. There are lots of edge cases that need tested around shift change, especially third shift, which starts before midnight, but for all the reporting and other facets of my software it is technically tomorrow.</p>
<p>So these time-dependant functions for the most part did not have useful, functional unit tests, until recently. In the past I would write my logic, cross my fingers and wait for the bug reports to come rolling in. I'm so thankful that I discovered this testing aid built in to the <a href="https://carbon.nesbot.com/docs/#api-testing">Carbon</a> PHP library. (If you haven't used Carbon, stop reading and go check it out, I'll forgive you. It makes working with dates and times in PHP a walk in the park, it is one of the most useful libraries I use!)</p>
<p>So now you are wondering, &quot;What is this wonderful function that will let me test my date/time based logic easier?&quot; I'm glad you asked. It is the <code>setTestNow()</code> function built in to the <a href="https://carbon.nesbot.com/docs/#api-testing">Carbon</a> api. Basically, this allows you to determine when <code>now()</code> is.</p>
<pre><code class="language-php">// instantiate a carbon object equal to '2019-01-06 23:15:00)
$testDate = Carbon::create(2019, 1, 6, 23, 15);
Carbon::setTestNow($testDate);
$date = new Carbon();
// $date = '2019-01-06 23:15:00'
</code></pre>
<p>The great thing is that this <code>now()</code> persists across other classes, allowing easy time-based unit testing.</p>
<pre><code class="language-php">&lt;?php
namespace Tests;
use App\Shift;
use Carbon\Carbon;
use PHPUnit\Framework\TestCase;
class ShiftTimesTest extends TestCase
{
public function testThirdShift()
{
$testDate = Carbon::create(2019, 3, 8, 23, 15);
Carbon::setTestNow($testDate);
$shift = new Shift();
$this-&gt;assertEquals(3, $shift-&gt;getCurrent());
}
}
</code></pre>
<p>Discovering this helper has allowed me to add tests to lots of previously untested areas of the code base, and allowed me to get away from PDD (Prayer Driven Development).</p>
Sat, 09 Mar 2019 00:00:00 UTCCreating an RSS Feed for a Symfony Bloghttps://eidson.info/post/creating-an-rss-feed-for-a-symfony-blog
<h1>Creating an RSS Feed for a Symfony Blog</h1>
<p><img src="/img/symfony_black_02.png" alt="" title="Symfony Logo" /></p>
<h2>Introduction</h2>
<p>One of the features I've wanted to add to this blog for a while now, but kept putting off, until now, is an RSS feed. I recently created an account on <a href="https://connect.symfony.com">connect.symfony.com</a> and there was a spot to add an RSS feed to one's profile, which was the only thing stopping me from getting my profile to 100% and earning the &quot;Profile completed&quot; badge. Nothing like a little gamification to make me stop putting off this task.</p>
<p>Since I'm never one to re-invent the wheel, without justification, I of course looked to see if there were any Symfony bundles that would allow me to easily add an RSS feed to my blog. &quot;Easily&quot; being the keyword in that sentence. I did find several of bundles, but all of them seemed to have convoluted configuration, with a learning curve much steeper than rolling my own.</p>
<p>Oh, yea, you can see it in action here: https://eidson.info/rss</p>
<h2>Rolling My Own</h2>
<p>So, with a mission in hand I headed over to my google machine. The first handful of hits showed an implementation using PHP's XMLWriter, which is probably the 'right' way to do it, and would have been the better choice, if the XMl I needed to generate was any more complex than it was, but it seemed like overkill for such a simple string. Luckily, I stumbled across a post on <a href="http://talkerscode.com/webtricks/create-rss-feed-using-php.php">talkerscode</a> which gave me a good starting point.</p>
<h3>Generating the XML</h3>
<p>The first class that I created was a class to create my xml string that I wanted to return as my response (shown below). It is basically a simple static function that takes an array of posts and creates a properly formatted XMl string creating an <code>item</code> element for each post. When I tried to run this, the first couple of posts were handled properly, and then it choked and died. It turns out that the title of one of my post's contained an ampersand ('&amp;'), which is not handled correctly by an xml parser, So I created a little helper function to escape any characters that were going to through the XML parsers for a loop.</p>
<pre><code class="language-php">&lt;?php
namespace AppBundle\Rss;
class Xml
{
public static function generate($posts)
{
$xml = &lt;&lt;&lt;xml
&lt;?xml version='1.0' encoding='UTF-8'?&gt;
&lt;rss version='2.0'&gt;
&lt;channel&gt;
&lt;title&gt;Todd Eidson's Programming Blog&lt;/title&gt;
&lt;link&gt;https://eidson.info&lt;/link&gt;
&lt;description&gt;Programming Blog&lt;/description&gt;
&lt;language&gt;en-us&lt;/language&gt;
xml;
foreach ($posts as $post) {
$title = self::xmlEscape($post-&gt;getTitle());
$url = self::xmlEscape($post-&gt;getUrl());
$slug = self::xmlEscape($post-&gt;getHtml());
$pubDate = $post-&gt;getPublished()-&gt;format('D, d M Y H:i:s T');
$xml .= &lt;&lt;&lt;xml
&lt;item&gt;
&lt;title&gt;{$title}&lt;/title&gt;
&lt;link&gt;https://eidson.info/post/{$url}&lt;/link&gt;
&lt;description&gt;{$slug}&lt;/description&gt;
&lt;pubDate&gt;$pubDate&lt;/pubDate&gt;
&lt;/item&gt;
xml;
}
$xml .= &quot;&lt;/channel&gt;&lt;/rss&gt;&quot;;
return $xml;
}
private static function xmlEscape($string) {
return str_replace(array('&amp;', '&lt;', '&gt;', '\'', '&quot;'), array('&amp;amp;', '&amp;lt;', '&amp;gt;', '&amp;apos;', '&amp;quot;'), $string);
}
}
</code></pre>
<h3>Creating a Controller</h3>
<p>So now that I had the XML generation working smoothly, I needed a way to handle an incoming request and return the appropriate response, which consists of the <code>Content-Type: text/xml;</code> header and the XML string. So I was able to create a Symfony controller that fetched the posts, created a response, set the headers, added the XML content, and returned the response.</p>
<pre><code class="language-php">&lt;?php
namespace AppBundle\Controller;
use AppBundle\Rss\Xml;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class RssController extends Controller
{
/**
* @Route(&quot;/rss&quot;, name=&quot;rss-feed&quot;)
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function rssAction()
{
$posts = $this-&gt;getDoctrine()
-&gt;getRepository('AppBundle:Post')
-&gt;fetch();
$response = new Response();
$response-&gt;headers-&gt;set(&quot;Content-type&quot;, &quot;text/xml&quot;);
$response-&gt;setContent(Xml::generate($posts));
return $response;
}
}
</code></pre>
<h3>Conclusion</h3>
<p>Now I had my rss feed up and running, I was able to get my <a href="https://connect.symfony.com">connect.symfony.com</a> profile to 100%, earn a badge, and scratch &quot;create an RSS feed&quot; off of my to-do list. There are a couple improvements that could be made. When I get more than 15 or 20 posts, I'll probably limit the response to the last 10 or so posts, and if I ever start to get a lot of traffic, I'll probably cache the XML and only update it when a new post is added, but remember kids, &quot;premature optimization is the root of all evil&quot;!</p>
<p>Thanks for reading. Feedback and/or questions are always appreciated!</p>
Sun, 03 Mar 2019 00:00:00 UTCOverride a trait in PHPhttps://eidson.info/post/ovveride-a-trait-in-php
<h1>Override a trait in PHP</h1>
<p><img src="/img/php.png" alt="php logo" title="php logo" /></p>
<p>I encountered a situation recently in which I wanted to change the method signature for a method that was injected into a class via a trait, namely changing the default parameter. I wanted to do this so I didn't have to pass in the new default parameter every place that I called this method on this particular class.</p>
<p>Overriding the method, was easy enough. As soon as a new method is declared in a class with the same name, the trait method is overridden. The tricky part was calling the 'parent' method from the 'child' method, so I didn't have to duplicate the logic inside my new method. I tried <code>parent::methodName()</code> and <code>TraitName::methodName()</code> before running off to the google machine to learn the proper way to do this.</p>
<p>It turns out that it is as easy as creating an alias for the trait method name in the &quot;Use&quot; statement, which made perfect sense after I saw it.</p>
<p>So, if this is the trait that you want to use and override:</p>
<pre><code class="language-php">trait SomeTrait {
public function someMethod(string $key = 'Id')
{
// logic
return $resultOfLogic;
}
}
</code></pre>
<p>Just give an alias to the trait method name when &quot;Using&quot; the trait as such:</p>
<p><code>use SomeTrait {someMethod as public traitSomeMethod;}</code></p>
<p>Here is a full example:</p>
<pre><code class="language-php">&lt;?php
class Something
{
use SomeTrait {someMethod as public traitSomeMethod;}
public function someMethod(string $key = 'Name')
{
return $this-&gt;traitSomeMethod($key);
}
}
</code></pre>
<p>So now I could call this method on any instantiation of this class without explicitly passing the default <code>$key</code> every time I needed to call it. Also, I had the added benefit of not having to duplicate the logic, keeping things DRY and ensuring that any changes made to the traits logic would 'bubble down' to the concrete implementation of the class.</p>
Sat, 23 Feb 2019 00:00:00 UTCGlobal Hooks with githttps://eidson.info/post/global-hooks-with-git
<h1>Global Hooks with Git</h1>
<p><img src="/img/git-logo.png" alt="" title="git logo" /></p>
<h2>Introduction</h2>
<p>Recently I began to wonder if there was a way to have a collection of <a href="https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks">git hooks</a> that could run on all of my git projects to save me the trouble of creating/editing hooks in each of my projects. Yes, it is possible to do this for new projects, via the <code>git config --global init.templatedir</code> command, but I have a lot of pre-existing git projects that I wanted to add a pre-push hook to, and I wanted to be able to make alterations to this hook after the fact that would affect all my projects. Apparently, I'm not the only person who needed this feature, because it was added in git release 2.9.</p>
<h2>Details</h2>
<p>Adding the global hooks was easy enough, thanks to this <a href="https://stackoverflow.com/a/37293198">stackoverflow</a> answer, but I did run into a couple of caveats after I had the global hooks path set.</p>
<h3>git config</h3>
<p>To add the path to your global git configuration run the following command:</p>
<pre><code class="language-bash">git config --global core.hooksPath /path/to/my/centralized/hooks
</code></pre>
<h3>Hook file</h3>
<p>The next step is to add your hook file and make it executable.</p>
<pre><code class="language-bash">touch /path/to/my/centralized/hooks/pre-push
chmod a+x /path/to/my/centralized/hooks/pre-push
</code></pre>
<p>And then add what ever logic you'd like the hook to execute. I use <a href="https://www.sonarqube.org/">sonarqube</a> to provide Continuos Inspection to my projects, so I wanted the <code>sonar-scanner</code> to run on every push. (I highly recommend <a href="https://www.sonarqube.org/">sonarqube</a> for keeping bugs and code smells out, you should check it out if you're not familiar with it!). I use the <a href="https://fishshell.com/">fish shell</a>, so you might need a different shebang.</p>
<pre><code class="language-bash"># /path/to/my/centralized/hooks/pre-push
#! /usr/bin/fish
command sonar-scanner
</code></pre>
<p>So I created my hook and did a test push, to see that it worked as expected. However, I do have some documentation only and small script projects that don't use the <code>sonar-scanner</code>. I was getting some ugly error messages when pushing these projects. It didn't fail the push, because I wasn't checking the return code on <code>sonar-scanner</code> command, but I still wanted to silence these messages, or not run <code>sonar-scanner</code> at all on projects that didn't need it. That was easy enough to do by checking for the presence of the <code>sonar-project.properties</code> file before running the scanner.</p>
<pre><code class="language-bash"># /path/to/my/centralized/hooks/pre-push
#! /usr/bin/fish
if test -e ./sonar-project.properties
command sonar-scanner
end
</code></pre>
<p>Ok, so now that is running only when it should, but I bumped into another issue. I had some projects that had project specific pre-push hooks that I expected to still be running before a push was executed. I had assumed that adding these global hooks would be in addition to the project hooks, not overriding them. However, that is not the behavior I was wanting; I still wanted any project specific hooks to be executed. The fix for this was to check for the existence of a project level git hook and fire it if it exists. I decided it would make more sense for my use case to fire it before the global hook logic was executed.</p>
<pre><code class="language-bash"># /path/to/my/centralized/hooks/pre-push
#! /usr/bin/fish
if test -e ./.git/hooks/pre-push
command sh ./.git/hooks/pre-push
end
if test -e ./sonar-project.properties
command sonar-scanner
end
</code></pre>
<h2>Conclusion</h2>
<p>So there I had my global hook, that only ran the <code>sonar-scanner</code> if it was necessary and made sure to also execute any local hooks. I'm sure I've only scratched the surface of the power of this, and I'm looking forward to adding more functionality in the very near future. I'm going to investigate failing the push if the <a href="https://www.sonarqube.org/">sonarqube</a> quality gate fails, next. To improve my CI/CD work flow. Have any suggestions or ideas for better hooks? Please leave them in the comments below.</p>
Sun, 17 Feb 2019 00:00:00 UTCVersion Bump for git using Fish Shellhttps://eidson.info/post/git-version-bump
<h1>Version Bump for git using Fish Shell</h1>
<p><img src="/img/fish-logo.png" alt="" title="Fish logo" /></p>
<h2>Intro</h2>
<p>One feature that I really like from npm is the <code>version</code> command which handles bumping either patch, minor, or major version number following the <a href="https://semver.org/">Semantic Versioning</a> standards. This sets the version attribute in your <code>package.json</code> file and creates a <a href="https://git-scm.com/book/en/v2/Git-Basics-Tagging">git tag</a> using the new version number.</p>
<p>For example you can run the <code>npm version minor</code> command from the root of an npm project and it will change the version from <code>1.2.12</code> to <code>1.3.0</code> write this out to your <code>package.json</code> file and create a git tag for the new version.</p>
<p>Since the vast majority of my projects are php projects and not npm, I don't get a chance to use this feature nearly as much as I would like, so I found myself wishing there was a way to do this directly from git.</p>
<h2>Details</h2>
<p>I have been a big fan of the <a href="https://fishshell.com/">fish shell</a> since first learning about it on <a href="https://syntax.fm/show/013/the-command-line-for-web-developers">syntax fm</a>'s &quot;The Command Line for Web Developers&quot; episode, mostly for the autosuggest and autocomplete features, but more recently I've discovered the powerful scripting features. So I decided to see if I could implement this functionality through the command line via a <code>fish</code> script.</p>
<p>So basically what I wanted to do was to write a script that would read the current <a href="https://git-scm.com/book/en/v2/Git-Basics-Tagging">git tag</a>, break it down into major, minor, and patch variables, increment the correct element, reassamble it into major.minor.patch format and create a new <a href="https://git-scm.com/book/en/v2/Git-Basics-Tagging">git tag</a>. Once this was working I realized that if the major or minor version was incremented I needed to reset the following elements to zero. After that was worked out, I thought that I could save myself another step if it went ahead and pushed the new tag to my remote repo.</p>
<p>At first I had it working with a custom function name, so from the root of my repo I could type <code>git_version minor</code> and the new tag was calculated, created, and pushed. However, I don't personally like typing underscores, if I don't have to. So I wondered if I could &quot;override&quot; the git command and look for my custom command and then call git with the command line arguments, if it didn't see my custom <code>version</code> command. That way it would feel like a more natural extension to git. That is when I came up with this solution:</p>
<pre><code class="language-bash"># ~/.config/fish/functions/git.fish
function git
if count $argv &gt; /dev/null
if [ $argv[1] = 'version' ]
git_version $argv
else
command git $argv
return $status
end
else
command git
return $status
end
end
</code></pre>
<p>This worked beautifuly. If <code>git version minor</code> is ran from the terminal, it calls my custom <code>git_version</code> function and passes the arguments to it, if anything other than <code>version</code> is passed as the first argument, it hands it off to git to handle. Of course, this can be altered to add many more custom commands to git, I'm looking forward to adding more functionality in the future.</p>
<p>And here is the custom function that is called if the <code>version</code> argument is passed to <code>git</code>. I'm sure there is room for improvements, but the few dozen times I've used it so far it behaved as expected. It expects an argument of either 'major', 'minor', or 'patch' to determine which element to bump, with an optional <code>build</code> argument of <code>alpha</code> or <code>beta</code> which will append a <code>-alpha</code> or <code>-beta</code> to the tag. There is also a <code>--force</code> flag which will create and push the tag even if there are uncomitted changes on the branch. The other flag is a <code>--dry</code> flag, if you just want to see the outcome of the command without creating a tag. Lastly, just running <code>git version</code> will display the current version.</p>
<pre><code class="language-bash"># ~/.config/fish/functions/git_version.fish
function git_version
set dry false
set build ''
set type ''
set force false
getopts $argv | while read -l key value
switch $key
case _
switch $value
case major minor patch
set type $value
case alpha beta
set build $value
end
case d dry
set dry true
case f force
set force true
case v version
_git_print_version
return 0
case \*
# Handle unknown flags here
echo unknown flag $key
end
end
set v (git describe --abbrev=0 --tags 2&gt;/dev/null)
if [ $status != 0 ]
set v '0.0.0'
end
# strip any thing from the hyphen after to remove -alpha or -beta
set v (string split &quot;-&quot; -- $v)[1]
set vmajor (string split &quot;.&quot; -- $v)[1]
set vminor (string split &quot;.&quot; -- $v)[2]
set vpatch (string split &quot;.&quot; -- $v)[3]
if [ $type = 'patch' ]
set vpatch (math $vpatch + 1)
else if [ $type = 'minor' ]
set vminor (math $vminor + 1)
set vpatch 0
else if [ $type = 'major' ]
set vmajor (math $vmajor + 1)
set vpatch 0
set vminor 0
else
echo $v
return 0
end
if [ $build ]
if [ $build = 'alpha' ]
set build alpha
else if [ $build = 'beta' ]
set build beta
else
echo &quot;The 'build' can only be blank, alpha, or beta&quot;
return 1
end
set tag $vmajor.$vminor.$vpatch-$build
else
set tag $vmajor.$vminor.$vpatch
end
if $dry
echo $tag
else
if git_is_dirty
if $force
echo 'Forcing new version'
else
echo 'git is dirty - must use --force'
return 1
end
end
git tag $tag
git push origin master --tags
end
end
function _git_print_version
echo git verison bump 1.2.0
end
</code></pre>
<h3>Conclusion</h3>
<p>Granted, this only works for a specific work flow, and the keystrokes it saves are negligible, but it was a neat learning experience and now I am ready to tackle some more fish scripting to make my life easier.</p>
<p>If you are interested in using this, it can be installed via <a href="https://github.com/jorgebucaran/fisher">fisher</a>:</p>
<pre><code class="language-fish">fisher add eidsonator/fish-git-version
</code></pre>
<p>The source code is available on github at <a href="https://github.com/eidsonator/fish-git-version">fish-git-version</a> and pull requests are welcome, if you see any room for improvement.</p>
<p>Please leave a comment if you can see any cons to me overriding git like this, or if you have any custom fish scripts you'd like to share.</p>
Sun, 10 Feb 2019 00:00:00 UTCAlphabetize your Way to More Readable Codehttps://eidson.info/post/alphabetize-for-more-readable-code
<h1>Alphabetize your Way to More Readable Code</h1>
<p><img src="/img/scrabble-tiles.jpeg" alt="" title="Scrabble pile" /></p>
<p>Super short and simple post this time, because it's explaining a simple concept. The concept is so simple, that I'm slightly embarrassed, almost shocked, that it took me almost 7 years of professional programming, and 3 and a half years of college to see and use this pattern.</p>
<p>The tip? Any time you are writing code and the order of the lines is irrelevant, such as declaring class variables, creating a JSON object, populating an associative array, adding dependencies, configuring your configuration, ad infinitum, use alphabetical order.</p>
<p>Instead of:</p>
<pre><code class="language-json">{
name: &quot;Marshall Mathers&quot;,
palms: &quot;sweaty&quot;,
knees: &quot;weak&quot;,
arms: &quot;heavy&quot;,
nervous: true,
sweater: &quot;mom's spaghetti&quot;
}
</code></pre>
<p>Use this:</p>
<pre><code class="language-json">{
arms: &quot;heavy&quot;,
knees: &quot;weak&quot;,
name: &quot;Marshall Mathers&quot;,
nervous: true,
palms: &quot;sweaty&quot;,
sweater: &quot;mom's spaghetti&quot;
}
</code></pre>
<p>Sure, it does not rhyme as well, but if you need to change <code>nervous</code> to false, it is much easier to find in the list. It does take a little extra brain power to add an item to the list, instead of just appending to the list, you may have to sing a phrase of the alphabet (unless you have a tool that sorts for you, see below). However, since code is read at an average of 10 times after it is written, you'll see the pay off when looking through a long JSON object or associative array to alter or fix something.</p>
<p>I used to try and use some sort of hierarchical order with grouping in most places that I use this now, but there is no real hierarchy in most places that this can be implemented. Take for an example a 'person' object or class. Sure, 'name' is pretty important and would always go first (if not a uid), but how do you order the rest of the fields? Is a phone number more or less important than an address? As far as packages and dependencies go, one package might be used a lot more than another package, but I'd argue that one is no more important than the other. If it wasn't important, it wouldn't be a dependency. In fact, it was when I started a new Symfony project a few months ago and noticed that they had added <code>&quot;config&quot;: {&quot;sort-packages&quot;: true}</code> to composer.json and the profound effect that it had had on the readability of the &quot;require&quot; section as to what packages I was using in a project that I it had dawned on me that I should be using alphabetical order in as many places as I could to improve readability.</p>
<p>It wouldn't really feel like one of my blog posts if I didn't somehow mention my favorite IDE, PhpStorm, so here it is: I've recently discovered a plugin, called <a href="https://plugins.jetbrains.com/plugin/5919-lines-sorter">Lines Sorter</a> by <a href="https://github.com/syllant">Sylvain Francois</a>, that will do your sorting for you. After you have the plugin installed, highlight the lines you wish to have sorted and then in the menu go to <code>Edit&gt;Sort Lines</code> or use the keyboard shortcut <code>alt + shift + L</code> (I had to unmap this shortcut from the default 'Load Context' option, first). This plugin will work in any of the JetBrains IDEs.</p>
<p>Is this something you've been doing for years? Do you have any tips that are so simple you can't believe how long it took you to incorporate them? Do you know of a VS Code plugin to accomplish this? Any arguments against using this tip? Please let me know in the comments.</p>
Sun, 10 Dec 2017 00:00:00 UTCfilter_var() is Your Friendhttps://eidson.info/post/filter_var-is-your-friend
<h1>filter_var() is Your Friend</h1>
<p><img src="/img/frustrated-mac-user.jpeg" alt="" title="Frustrated programmer" /></p>
<h2>Intro</h2>
<p>I was recently reading a blog post by Aaron Saray called
<a href="https://aaronsaray.com/2017/in-php-false-is-sometimes-true">In PHP, False is Sometimes True</a>.
This is an issue that I've encountered in the past and I'd already considered
blogging about the solution, which is something Aaron left out of his blog post.</p>
<h2>The Issue</h2>
<p>I'm sure that almost everyone that has dealt with handling html form data on the
backend from a <code>$_POST</code> or a <code>$_GET</code> variable via http or a JSON string has
encountered a situation in which trying to use a boolean value resulted in the
strange behavior of &quot;false&quot; equaling true. This happens because when casting a
string to a boolean, any non-empty string evaluates to true.</p>
<p>Mr. Saray used the following code snippet to demonstrate this &quot;phenomenon&quot;.</p>
<pre><code class="language-php">$flag = &quot;false&quot;;
assert((bool) $flag === true);
</code></pre>
<p>Of course, the assetion here returns true, because &quot;false&quot; <strong>IS</strong> true.</p>
<h2>The Solution</h2>
<p>In the past, before I learned about the filter_var function I would do something
like <code>assert($flag === &quot;true&quot;);</code> This solution is perfectly valid, however, it
is also perfectly inflexible. If we want to support multiple frontends, some
which may actually send a boolean, or some that may use a 0 = false and 1 = true
schema, this will fail and leave us hunting bugs again.</p>
<p>Introduced in php 5.2 and still valid in php 7+,
<a href="http://php.net/manual/en/function.filter-var.php">filter_var()</a> is the best way
to tackle this problem. filter_var takes 3 arguments, the variable to filter,
the type of filter to use and optional filters, which are dependent on the type
of filter.</p>
<p>Using a filter type of <code>FILTER_VALIDATE_BOOLEAN</code> will return true for 1, &quot;1&quot;,
true, &quot;true&quot;, &quot;on&quot; and &quot;yes&quot;. Any other value will return false. So this solves
the inflexibility issue that arrises with my 'old' solution.</p>
<p>Solving the above bug with filter_var would look like this:</p>
<pre><code class="language-php">$flag = &quot;false&quot;;
$boolFlag = filter_var($flag, FILTER_VALIDATE_BOOLEAN);
assert($boolFlag === true);
</code></pre>
<h2>Conclusion</h2>
<p>I've demonstrated that using filter_var with the FILTER_VALIDATE_BOOLEAN filter
type is much more predictable than simply casting the variable, and much more
flexible than a hard coded solution. However, as implied by having a 'type'
parameter in the filter_var function, you can do more than just safe boolean
casting with this function. Two of my other most used filter types are
FILTER_VALIDATE_EMAIL and FILTER_VALIDATE_IP which do pretty much as their names
imply. If the variable is a valid email or IP address, they will return the
variable, if not they return false. These are super useful in if statements, so
throw out those long confusing regular expressions that you googled that miss
edge cases anyway and start using filter_var. You can find a list of the other
<a href="http://php.net/manual/en/filter.filters.validate.php">Validate Filters here</a>.
There are also
<a href="http://php.net/manual/en/filter.filters.sanitize.php">Sanatize filters</a> that
will return an altered variable, so you can sanitize your inputs. Last but not
least, check out
<a href="http://php.net/manual/en/function.filter-var-array.php">filter_var_array()</a> If
you have an array of flags, email or IP addresses that you need to validate in
one fell swoop.</p>
Mon, 04 Dec 2017 00:00:00 UTCCreate a File Watcher for php-cs-fixer in PhpStormhttps://eidson.info/post/phpstorm-file-watcher-php-cs-fixer
<h1>Create a File Watcher for php-cs-fixer in PhpStorm</h1>
<p>
<img src="/img/phpstorm-2017_3-php-cs-fixer-linux.png" alt="File Watcher Settings for Linux" title="PhpStorm" style="width: 100%">
</p>
<h2>Intro</h2>
<p>This is a quick an easy guide to setting up a file watcher on <a href="">PhpStorm</a> so that every time a php file is saved,
<a href="https://github.com/FriendsOfPHP/PHP-CS-Fixer">php-cs-fixer</a> is ran on the file. More than just a linter, php-cs-fixer will update your code to match coding standards
such as the official PSR-1 and PSR-2, as well as community standards such as the <a href="">Symfony</a> one. It will also do some
modernization and micro-optimizations.</p>
<h2>Steps</h2>
<h3>Install php-cs-fixer</h3>
<p>There are a few different installation options, but the <a href="">Composer</a> install seemed like the easiest (like it always does).
If you don't have composer installed you can follow the link above to install it. After Composer is installed, from the
terminal run:</p>
<pre><code class="language-bash">$ composer global require friendsofphp/php-cs-fixer
</code></pre>
<p>After it installs you can try and run it from the terminal.</p>
<pre><code class="language-bash">$ php-cs-fixer --help
</code></pre>
<p>If it doesn't run, it'll need added to the path. Here is a linux command, my Windows box worked out of the box. I'm
assuming the Composer Windows installer handled this for me.</p>
<pre><code class="language-bash">$ export PATH=&quot;$PATH:$HOME/.composer/vendor/bin&quot;
</code></pre>
<h3>Create the PhpStorm File Watcher</h3>
<p>From inside of a project in PhpStorm, open up the settings page. From the menu go to <code>File &gt; Settings</code> or use the keyboard
shortcut <code>ctrl+alt+s</code> (in Windows or linux).</p>
<p>From there you can start typing 'file watcher' to narrow down the options and then select <code>File Watchers</code> from under the
<code>Tools</code> tab.</p>
<p>Next either press <code>alt + insert</code> or press the green plus sign icon in the upper right-hand corner to create a new file watcher.</p>
<p>Choose the <code>Custom Template</code> option.</p>
<p>In the dialog box that opens, give your watcher a name, I chose &quot;php-cs-fixer&quot;, for the sake of simplicity.</p>
<p>Set the File type to &quot;PHP&quot; and Scope to &quot;Current File&quot;.</p>
<p>Set the Program to &quot;php-cs-fixer&quot;. In my Windows environment, I had to add the '.bat' file extension (example below).
In my linux environment I had to use the full path to my <code>~/composer/vendor/bin/php-cs-fixer</code> (example above). Run
<code>which php-cs-fixer</code> from the terminal to get the full path. This command works on Windows 10, too.</p>
<p>The Arguments is where all the work is done. First type <code>fix</code> which is the command for php-cs-fixer to actually do something.
Next add any flags you want to pass in for the rules. Finally add <code>$FilePath$</code> which is a PhpStorm variable for the full
path to current file, up to and including the name and extension.</p>
<p>Set the &quot;Output paths to refresh&quot; to <code>$FilePath$</code> so the editor reload the current file as soon as the changes are saved.</p>
<p>The final step and a very important one is to uncheck the &quot;Auto-save edited files to trigger the watcher&quot; checkbox
under &quot;Advanced Options.&quot; If this is checked,
the watcher will run with each keystroke in the file editor and PhpStorm will become confused if the memory (editor) changes
or the disk(php-cs-fixer) changes are the ones to use. If you are still on PhpStorm 2017.2 this option is labeled &quot;Immediate file synchronization&quot;.</p>
<p>Click &quot;OK&quot; to save your file watcher, and then close the settings dialog.</p>
<p>
<img src="/img/file-watcher-php-cs-fixer-windows.png" alt="File Watcher Settings for Windows" title="PhpStorm" style="width: 100%">
</p>
<h2>Conclusion</h2>
<p>Setting up this file watcher in PhpStorm is super easy and crazy useful.</p>
<p>Another option would have been to use the external tools option of PhpStorm, which is the original
way I was going to do this, inspired by a <a href="https://laracasts.com/series/how-to-be-awesome-in-phpstorm/episodes/26">Laracasts tutorial</a>.
The only downfall to using php-cs-fixer as an external tool, is that you have to manually trigger
it. I wanted php-cs-fixer to be a fully automated step in my work flow.</p>
<p>One more, fully automated, way to integrate php-cs-fixer would be to use a git pre-commit hook.
I still like the file watcher option better, because it allows me to see in the editor if there
are still warnings from other linters and sniffers if there are things that could still be
improved even after php-cs-fixer is ran.</p>
Thu, 30 Nov 2017 00:00:00 UTCphp 7.3 - Flexible heredoc & nowdoc Syntaxhttps://eidson.info/post/php-flexible-heredoc-nowdoc-syntax
<h1>php 7.3 - Flexible heredoc &amp; nowdoc Syntax</h1>
<p><img src="/img/php.png" alt="php logo" title="php logo" /></p>
<p>Although we've still got a while to go before we see php 7.3, since we're still 4 days away from the release of php 7.2,
I've already seen one new feature that looks like it will make its way into 7.3 that I am excited about. This feature
is more flexible syntax for heredoc and nowdoc statements. Here is the official <a href="https://wiki.php.net/rfc/flexible_heredoc_nowdoc_syntaxes">rfc</a>
if you'd like to read it.</p>
<h2>What are heredocs and nowdocs?</h2>
<p>Heredocs and nowdocs are the easiest and cleanest ways in php to use and format multiline strings.</p>
<p>Instead of:</p>
<pre><code class="language-php">$html = '&lt;ul&gt;';
$html .= '&lt;li&gt;item 1&lt;/li&gt;';
$html .= '&lt;li&gt;item 2&lt;/li&gt;';
$html .= '&lt;li&gt;item 3&lt;/li&gt;';
$html = '&lt;/ul&gt;';
</code></pre>
<p>We can use:</p>
<pre><code class="language-php">$html = &lt;&lt;&lt;html
&lt;ul&gt;
&lt;li&gt;item 1&lt;/li&gt;
&lt;li&gt;item 2&lt;/li&gt;
&lt;li&gt;item 3&lt;/li&gt;
&lt;/ul&gt;
html
</code></pre>
<p>The only difference between a heredoc and a nowdoc is that a heredoc performs string interpolation, turning your variables
into the string they represent, while a nowdoc does not.</p>
<pre><code class="language-php">//heredoc example
$name = 'Todd Eidson';
$text = &lt;&lt;&lt;txt
My name is $name
txt
echo $text;
// outputs 'My name is Todd Eidson'
</code></pre>
<pre><code class="language-php">//nowdoc example
$name = 'Todd Eidson';
// notice the single quotes around the marker
$text = &lt;&lt;&lt;'txt'
My name is $name
txt
echo $text;
// outputs 'My name is $name'
</code></pre>
<p>One great thing about using a heredoc/nowdoc within a good IDE (like my favorite,
<a href="https://www.jetbrains.com/phpstorm/">PhpStorm</a>) is that php allows you to pick your own heredoc marker, and PhpStorm
is smart enough to give you syntax highlighting inside the heredoc based on the marker
used. For example if you use <code>sql</code> or <code>HTML</code> for your marker name, your heredoc
string will use the code highlighting of the marker, making mistakes easy to spot.</p>
<h2>Caveat</h2>
<p>The only caveat (for now) when using a heredoc/nowdoc is that the end of statment marker must be the first and only thing
on the line. This leads to left aligned text in the middle of a function or method that can be quite jarring when quickly
scanning code, much like coming to a stop sign in the middle of an interstate, your brain has to slow down for a second to
figure out why your indentation is not being properly followed.</p>
<p>Like so:</p>
<pre><code class="language-php">class MyClass
{
public function MyFunction($variable)
{
if ($variable) {
$html = &lt;&lt;&lt;html
Why is this code against the left margin?
It would be really nice if it was
properly indented.
html
}
return $html;
}
}
</code></pre>
<h2>The Changes</h2>
<p>In php 7.3 we will be able to indent the end of heredoc marker to improve readability.
Any whitespace before ending marker will also be stripped off the front of the each
line in the multiline string. Any line that is not indented to at least the level
of the ending marker will throw an error.</p>
<p>An example:</p>
<pre><code class="language-php">class MyClass
{
public function MyFunction($variable)
{
if ($variable) {
$html = &lt;&lt;&lt;html
Isn't this so much easier to read?
It is really nice that it is
properly indented.
And so much easier to read!
html
}
return $html;
}
}
</code></pre>
<p>The other chage is that the ending marker does not have to be followed by a new line.
I can't remember a time at which I wished for this ability, so I'm not nearly as
excited about this as I am the ability to indent the ending marker, but I'm sure
some people will get some use out of it. I guess it could be useful if using multiple
heredocs in a function call or an array.</p>
<p>Like this:</p>
<pre><code class="language-php">// The old way:
myFunction(&lt;&lt;&lt;txt
This is
the first parameter
txt
, &lt;&lt;&lt;txt
This is
the second parameter
txt
);
// The new way
myFunction(&lt;&lt;&lt;txt
This is
the first parameter
txt, &lt;&lt;&lt;txt
This is
the second parameter
txt
);
</code></pre>
<h2>Conclusion</h2>
<p>I'm really looking forward to when I can get switched over to 7.3 (or 8, whichever comes
first) so I can take advantage of this new feature and clean up all my heredocs. I do
recommend reading the <a href="https://wiki.php.net/rfc/flexible_heredoc_nowdoc_syntaxes">rfc</a> as
there are some nuances concerning marker names and a raised backwards incompatability issue
that I don't go over in this post.</p>
<p>What are your thoughts on this change? Yay, nay, or meh?</p>
Sun, 26 Nov 2017 00:00:00 UTCThe Joy of Rotating Logs in Symfonyhttps://eidson.info/post/rotating-logs-symfony
<h1>The Joy of Rotating Logs in Symfony</h1>
<p><img src="/img/logs.jpg" alt="logs" title="Logs" /></p>
<p>Switching from my hand-made, hodgepodge, cobbled together collection of libraries that
was trying to act more and more like a &quot;framework&quot; every day to a full-blown real, properly
developed, properly tested framework like Symfony continues to be the best decision I've made
in my programming career thus far. I've learned so much about clean code, design patterns,
SOLID principles and many other programming best practices from working within Symfony's
MVC (Model View Controller) pattern and reading its documentation and code when I need to
extend it to bow to my every whim.</p>
<p>One great feature of Symfony is the highly configurable logging, implemented via monolog.<br />
Way back in my pre-Symfony days, when I encountered an exception in development, my first step was
firing up xdebug and stepping through the code line by line to inspect variables and watch where
the logic was taking me to try and find the root cause of the bug. Now my first step is to head
to the log file and see what was happening at the time of the exception (for JSON calls, anyway.
The log is spit out on the screen if the result of the call was to render a page).</p>
<p>I prefer text logging verses logging to a database, for the simplicity of writing and reading.<br />
One problem with text logging is that the files can grow too big, too fast. Most text editors
will choke on a log file that is too big. Or, the worst case scenario may be encountered, which
is the log file becomes so large that it eats up all available disk space on the server, bringing
the server to its knees. Thankfully I've only encountered this once, due to leaving a debug flag on
in production. Which brings up another great thing about using Symfony, thanks to the app_dev.php file,
no more debug flags.</p>
<p>To combat the issue of log files growing too large, one of the first things I do in any new Symfony
project is to set the log type to <code>rotating_file</code> which is a standard feature in monolog, but beautifully
exposed via the Symfony configuration file.</p>
<p>This can be set in both your prod and dev config files, to give the desired behavior for each environment.</p>
<h3>Development</h3>
<p>In the <code>config_dev.yml</code> simply change the <code>main</code> handler type from <code>stream</code> to <code>rotating_file</code> and just
below that add the <code>max_files</code> to keep. I set mine to <code>1</code> in dev, since I don't believe that a development
log file needs to persist past a single day. Voilà, a fresh clean log file every morning when I access my log
in the development environment.</p>
<pre><code class="language-yml"># app/config/config_dev.yml
monolog:
handlers:
main:
# change this line
type: rotating_file
# add this line
max_files: 1
path: '%kernel.logs_dir%/%kernel.environment%.log'
level: debug
channels: ['!event']
console:
type: console
process_psr_3_messages: false
channels: ['!event', '!doctrine', '!console']
# To follow logs in real time, execute the following command:
# `bin/console server:log -vv`
server_log:
type: server_log
process_psr_3_messages: false
host: 127.0.0.1:9911
</code></pre>
<h3>Production</h3>
<p>In your project's production environment configuration file - <code>config_prod.yml</code>, we'll make the same changes,
but under the <code>nested</code> handler. The nested handler is another great aspect of logging with monolog from inside
of a Symfony project. If the <code>main</code> handler is set to a <code>fingers_crossed</code> type, it caches the log for every
request. The only time that it logs anything, is if the <code>action_level</code> threshold is passed. In the example below,
if a log level of error or higher is caught, it passes the cached log to the handler set in the <code>handler</code> parameter.
This allows logging of the full request stack, but only in the event that an error occurs. This way only
meaningful logs are stored, but we get the entire log for that request. This is another feature that keeps are
logs from growing too large.</p>
<pre><code class="language-yml"># app/config/config_prod.yml
monolog:
handlers:
main:
type: fingers_crossed
action_level: error
handler: nested
nested:
# change this line
type: rotating_file
# add this line
max_files: 7
path: &quot;%kernel.logs_dir%/%kernel.environment%.log&quot;
level: debug
console:
type: console
process_psr_3_messages: false
</code></pre>
<h3>Log files location</h3>
<p>Another thing I like to do with the logging, is change the location of where my log files are stored. By default,
the log files are stored in <code>project_root/var/logs</code>. My deployment process creates each new release in a <code>releases</code>
directory in my production environment, and my webroot is nothing more than a symlink that that points to the
most recent releases directory. If I keep the default log file location, each release uses its own directory
to store log files. By moving the logs directory up one level, each release uses a shared log location so
my log files persist across new releases of my project. Another benefit to this is not having to worry about
setting write permissions for the www-data user that Apache uses for the log directory in each new release.
It is easy to alter the <code>getLogDir()</code> method in your <code>AppKernel</code> class to use one level up, or any other custom
location in which you wish to store your log files.</p>
<pre><code class="language-php"> // project_root/app/AppKernel.php
public function getLogDir()
{
// I've inserted the '../' to move the logs up one directory from the project root
return dirname(__DIR__).'/../var/logs';
}
</code></pre>
<h3>Easy log file viewing</h3>
<p>As easy as it is to view log files in development, to logs in your production environment, you have to log
in to your production server, navigate to the log directory and then open them with the log viewer/text editor
of your choice. It was those couple extra steps that inspired me, after not finding any existing solutions
that I liked, to write a Symfony bundle that allows you to view your logs from your web browser.<br />
My WebLogViewerBundle includes color-coded, collapsable log levels, and formatted JSON and SQL.
It can be included via Composer (<a href="https://packagist.org/packages/greenskies/web-log-viewer-bundle">packagist</a>)
and the source can be found on <a href="https://github.com/greenskies/WebLogViewerBundle">GitHub</a>.</p>
<h3>Conclusion</h3>
<p>Hopefully, you can see the benefits and ease of using rotating log files in your Symfony projects. How do you
configure your logging in Symfony?</p>
Fri, 24 Nov 2017 00:00:00 UTCEditing Shared Libraries in PhpStorm with Composer and githttps://eidson.info/post/editing-shared-libraries-in-phpstorm-with-composer-and-git
<h1>Editing Shared Libraries in PhpStorm with Composer and git</h1>
<p><img src="/img/logo-composer-transparent4.png" alt="Composer logo" title="Composer Logo" /></p>
<h2>The &quot;Old&quot; Workflow</h2>
<p>When I started my current position way back in the winter of 2013 as the sole Application Developer in a
corporate/enterprise environment, I was tasked with maintaining existing web applications, porting Visual Basic
apps into a web environment, as well as creating new applications. Each of the php applications that I had inherited
had several shared dependencies that were maintained independently in their separate project directories.
Any bug that was found and fixed in one of these 'libraries' had to be copied manually to the other projects
that were using this library. Seeing this as a clear violation of the DRY (don't repeat yourself) principle,
I decided to move the libraries into a central location that could be shared among the different projects via the
php include path. This approach worked fine, until I wanted to start introducing changes that broke backwards
compatibility for the benefit of one project. It would break the other projects until they had been updated to
use the newer version of the library. (I was still using manual deployment, no unit testing, no frameworks, it was a
dark and dreary time.)</p>
<h2>Take Two</h2>
<p>It was about this time that I realized that it would indeed be best to keep individual copies of the libraries
with each project, to prevent the aforementioned problems with backwards compatibility breaking changes, but these
libraries needed to be managed from a central location. I had recently convinced my manager that we should switch
from svn to git, and I thought that maybe using <a href="https://git-scm.com/docs/git-submodule">git-submodule</a> would be
the answer to the question of how to manage these dependencies. It wasn't. It was messy. It was broken. It was
the worst idea I had had in a long series of bad ideas in trying to tackle this problem. It was also about this
time that I had realized that what I was trying to do was write my own framework. I had a database connection library,
a library that auto-wired my templating engine, an ldap connection library... I needed to stop trying to reinvent the
wheel and just learn and use a real framework.</p>
<h2>Composer to the Rescue</h2>
<p>I decided to learn and implement the <a href="https://symfony.com/">Symfony Framework</a>. Learning Symfony included learning
about <a href="https://getcomposer.org/">Composer</a> which I was vaguely familiar with, but totally unaware of how powerful it is.
In hindsight I should have realized that a &quot;Dependency Manager&quot; was exactly what I needed to manage my dependencies.
I soon learned that I could include my own repositories in my projects via the Composer configuration. Using this I
could make changes to my library inside of my project, copy these changes to my library repository, upload the changes
to my central repository and then get the changes in my other projects by using <code>composer update</code>. This was a couple
extra steps than I wanted to take, but it was the workflow I had been looking for all along.</p>
<h2>Composer, git, and PhpStorm</h2>
<p>I soon realized that when one includes a repository with a type of 'vcs' through composer, you not only get a copy
of the files in that project, you get a copy of the entire repo, up to and including the <code>.git</code> directory. So basically
I could make changes to my repo from inside of my <code>vendor</code> directory and commit and push to my central repository
straight from there. When I learned that I could inform my favorite IDE <a href="https://www.jetbrains.com/phpstorm/">PhpStorm</a>
about these 'sub' repositories and commit and push directly from the user interface my current workflow was concreted
and perfected (for now).</p>
<h2>Steps to implement this process</h2>
<ul>
<li>In the project's <code>composer.json</code> file add a <code>repositories</code> section pointing to your shared library.</li>
<li>Add your repository as a dependency in the <code>require</code> section
<ul>
<li>This will also work if use <a href="https://github.com/composer/satis">satis</a> to require your repositories</li>
</ul>
</li>
</ul>
<pre><code class="language-json">{
&quot;repositories&quot;: [
{
&quot;type&quot;: &quot;vcs&quot;,
&quot;url&quot;: &quot;git@github.com:greenskies/WebLogViewerBundle.git&quot;
}
],
&quot;require&quot;: {
// other dependencies
&quot;greenskies/web-log-viewer-bundle&quot;: &quot;dev-master&quot;
}
}
</code></pre>
<ul>
<li>Open up the settings in PhpStorm via File &gt; Settings or <code>ctrl + alt + s</code> (in Windows or Linux)</li>
<li>Click on the <code>Version Control</code> tab</li>
</ul>
<p>
<img src="/img/Settings.png" alt="PhpStorm Settings" title="PhpStorm" style="width: 100%">
</p>
<ul>
<li>Click on the green <code>+</code> (plus sign) in the upper right hand corner of the dialog to add another vcs path</li>
<li>Add the path to your library inside of your vendor folder - PhpStorm should select the <code>git</code> vcs type for you</li>
</ul>
<p>
<img src="/img/Add_VCS_Directory_Mapping.png" alt="Add VCS Directory Mapping" title="Add VCS Directory Mapping" style="width: 100%">
</p>
<ul>
<li>Now, anytime you make any change to your shared library, you can select &quot;git &gt; Commit file&quot; or &quot;Commit Directory&quot; to
commit and push your changes! (You can also use git from the command line/terminal from inside of shared library to commit &amp; push)</li>
</ul>
<p>Do you have any tips and tricks to integrate git, Composer, and PhpStorm into your worklow? If so, please share
them in the comments.</p>
Sun, 19 Nov 2017 00:00:00 UTCPHP_EOL is Broken (Sometimes)https://eidson.info/post/php_eol_is_broken
<h1>PHP_EOL is Broken (Sometimes)</h1>
<p><img src="/img/php.png" alt="php logo" title="php logo" /></p>
<h3>What is PHP_EOL?</h3>
<p>Introduced in version 5.0.2 of php, <code>PHP_EOL</code> is a string constant that represents the correct end of line symbol for
the platform that you are running php on.
So on Windows this should be set to <code>&quot;\r\n&quot;</code> (carriage return and line feed) and on a *nix system it should be set to
<code>&quot;\n&quot;</code> (only line feed).</p>
<h3>Where is it Used?</h3>
<p>You <strong>SHOULD</strong> use it when programmatically creating a text file via php.</p>
<pre><code class="language-php">$text = 'Line one' . PHP_EOL;
$text .= 'Line two' . PHP_EOL;
$file = fopen('file.txt', 'w');
fputs($file, $text);
fclose($file);
</code></pre>
<p>This will create a platform correct end of line separator, and ensure portability in a project.</p>
<h3>Okay, So How is it Broken?</h3>
<p>Usually when one is working with strings that contain multiple lines and they want to create an array that consists of
each individual line they will use:</p>
<pre><code class="language-php">$array = explode(PHP_EOL, $string);
</code></pre>
<p><em>However,</em> in the last couple of weeks I've been bitten by two different bugs caused by the very simple line of code above.</p>
<h5>Bug #1</h5>
<p>The first was when I was working on my <a href="https://github.com/eidsonator/WebLogViewerBundle">Web Log Viewer Bundle</a> project
which is a <a href="https://symfony.com/">Symfony</a> bundle for viewing log files created by a Symfony project online, so logging
in to the server to view them in not necessary. This project parses log files, formats the lines, and displays them
in an HTML table. I was using <code>$array = explode(PHP_EOL, $string);</code>, but when running this on a Windows box, my string
was not exploding correctly and I was getting <code>$array = [$string]</code> instead of <code>$array = [line1, line2, line3, ...]</code>.</p>
<p>Symfony uses <a href="https://github.com/Seldaek/monolog">monolog</a>, and I didn't investigate how monolog writes its end of line
symbols in an attempt to determine the root cause of this bug, but I did need to find a fix.
<em>Help me stackoverflow, you're my only hope.</em></p>
<h5>Bug #2</h5>
<p>I've recently started using <a href="http://www.magephp.com/">Magallanes</a> to deploy my projects, instead of my old hacky way of
using a git post commit hook to push my changes to a git repo on the production server and then logging in to the production
server and manually performing 5 or 6 steps to update dependencies, build assets, and clear caches. I did have to make
a handful of really small changes to make it work in a Windows environment, but oh, man, was it worth it. Lots more on
how I improved my deployment process with Magallanes in later posts.</p>
<p>I mentioned that I had to make some changes to make Magallanes work in a Windows environment, and I thought that I had
everything worked out until I noticed this next bug. I use the &quot;releases&quot; option of Magallanes that uploads the current
release to a timestamp-based-name directory inside of the <code>releases</code> directory and then creates a symlink named <code>current</code>
that points to the newest directory in the <code>releases</code> folder. In the Magallanes config file, there is a parameter named
<code>releases</code> that indicates the number of previous releases that should be kept on the server, in case there is a need to
rollback to an earlier release. I noticed that in one of my <code>releases</code> directory, there were about 10 previous releases,
when I had this configuration parameter set to 5. Something was broken.</p>
<p>I went looking through the <a href="https://github.com/andres-montanez/Magallanes/blob/master/src/Task/BuiltIn/Deploy/Release/CleanupTask.php">cleanup task code</a>
and discovered that it was using <code>ls -1</code> via ssh to get a string of all the directories inside of the <code>releases</code> directory
and then using my recent archnemesis <code>$releases = explode(PHP_EOL, trim($releases));</code> to turn that string into an array
and doing all the work on the array. I was pretty confident that the bug was in the explode statment, due to my recent
experience with Bug #1. After stepping through the code using xdebug, my hunch was confirmed, and I knew just where to
find the fix.</p>
<h3>The Fix</h3>
<blockquote>
<p>Some people, when confronted with a problem, think &quot;I know, I'll use regular expressions.&quot;
Now they have two problems. - Jamie Zawinski</p>
</blockquote>
<p>After discovering Bug #1, I fired up my trusty google machine and went in search to a solution for this problem.
Sure enough, the first search result was a <a href="https://stackoverflow.com/a/5053394">stackoverflow answer</a> that fixed the bug.
It was the following simple, one-line, cross-platform fix:</p>
<p><em>Replace:</em></p>
<pre><code class="language-php">$lines = explode(PHP_EOL, $str);
</code></pre>
<p><em>With:</em></p>
<pre><code class="language-php">$lines = preg_split('/\n|\r\n?/', $str);
</code></pre>
<p>So, of course, I knew the perfect fix when I came across Bug #2, just a few short weeks later.</p>
<h3>Conclusion</h3>
<p>Although I was more concerned with fixing the bugs than I was with finding the root cause of the bugs, which would have
required I solve the riddle &quot;when is the end of line not the end of the line?&quot;, I was able to implement a nice and easy
cross-platform solution and come to the conclusion that PHP_EOL is Broken (Sometimes).</p>
Sun, 12 Nov 2017 00:00:00 UTCCode Highlighting in HTMLhttps://eidson.info/post/2017-10-22_code_highlighting
<h1>Code Highlighting in HTML</h1>
<p><img src="/img/computer_code.png" alt="alt text" title="Highlighted Code" /></p>
<p>I've been wanting to start blogging for quite some time now, and I figured there is no time like the present.
I am familiar with both <a href="https://wordpress.com">WordPress</a> and <a href="https://www.drupal.org/">Drupal</a>, but I wanted to &quot;roll my own&quot; both for flexibility and as a learning experience.
Since this blog is going to be code heavy, one thing that was really important to me was code highlighting in the display.
I really like the code highlighting on the <a href="http://symfony.com/doc/current/setup.html">Symfony documentation pages</a>, and I've used that in some of my own documentation pages,
however, that is using <a href="http://www.sphinx-doc.org/en/stable/">Sphinx</a> and <code>.rst</code> files, which requires a compilation step. I was looking for a way to have markdown files parsed by a real-time HTML converter to give me syntax highlighted code in HTML.
That's how I discovered <a href="https://highlightjs.org/">highlightjs</a>.</p>
<p><em>highlightjs</em> will take any code that inside of an element that has a class of <code>{language-name}</code>, <code>lang-{language-name}</code>, or <code>language-{language-name}</code>
and wrap keywords, built-ins, and strings/numbers in spans that have highlighting classes assigned to them.
There is a cdn version available that has support for 23 of the most popular languages that can be added to your project in
3 easy steps.</p>
<ul>
<li>First add the stylesheet to the <code>head</code> section of the HTML page.</li>
</ul>
<pre><code class="language-html">&lt;link rel=&quot;stylesheet&quot; href=&quot;//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css&quot;&gt;
</code></pre>
<ul>
<li>Next add the JavaScript to the end of your <code>body</code> element.</li>
</ul>
<pre><code class="language-html">&lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js&quot;&gt;&lt;/script&gt;
</code></pre>
<ul>
<li>Finally, after the JavaScript is loaded, fire off the <code>initHighlightingOnLoad()</code> function to add the formatting.</li>
</ul>
<pre><code class="language-html">&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt;
</code></pre>
<p>Now that the css and JavaScript is loaded and the OnLoad function is taken care of, we can throw some code at it to be
highlighted.</p>
<ul>
<li>In a markdown file, any text that is encased in triple backticks will be treated as code upon parsing, the language
can be added after the opening set of backticks. If the language is not present <em>highlightjs</em> will make a best guess
to which language it is.</li>
</ul>
<pre><code class="language-markdown">```javascript
var s = &quot;JavaScript syntax highlighting&quot;;
window.alert(s);
var num = 42;
```
</code></pre>
<ul>
<li>The parsed HTML will appear as such. <em>The class is derived from the language appended to the triple backticks in the above step</em>
(This will also work on raw HTML written as below, if it is not being parsed from a markdown file)</li>
</ul>
<pre><code class="language-html">&lt;pre&gt;
&lt;code class=&quot;language-javascript&quot;&gt;
var s = &quot;JavaScript syntax highlighting&quot;;
window.alert(s);
var num = 42;
&lt;/code&gt;
&lt;/pre&gt;
</code></pre>
<ul>
<li>The highlighted results of the parsed markdown will appear like this:</li>
</ul>
<pre><code class="language-javascript">var s = &quot;JavaScript syntax highlighting&quot;;
window.alert(s);
var num = 42;
</code></pre>
<p>It is really quite simple to implement this powerful code highlighting library, and if the 23 languages included in the
hosted version don't cover a particular language that you need to highlight you can go to their <a href="https://highlightjs.org/download/">download</a>
page to build a custom version which can include support for any of 176 different languages, which is what I'll be switching
to as soon as I write my first post that requires highlighting for the twig templating language.</p>
Sun, 22 Oct 2017 00:00:00 UTC