<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Stage Right Labs</title>
  <subtitle>Ideas and musings about software and web application development.</subtitle>
  <link href="https://stagerightlabs.com/feed" rel="self" />
  <link href="https://stagerightlabs.com" />
  <updated>2026-06-04T17:49:17+00:00</updated>

  <author>
    <name>Ryan C. Durham</name>
    <uri>https://stagerightlabs.com</uri>
  </author>

  <id>https://stagerightlabs.com/</id>
  <icon>https://stagerightlabs.com/img/compact.png</icon>
  <logo>https://stagerightlabs.com/img/compact.png</logo>
  <rights>©2026 Ryan C. Durham</rights>

  <image>
    <link>https://stagerightlabs.com/</link>
    <title><![CDATA[Stage Right Labs]]></title>
    <url>https://stagerightlabs.com/img/compact.png</url>
  </image>

    <entry>
    <title>
      <![CDATA[Automating Wayfinder Without Vite]]>
    </title>
    <id>tag:stagerightlabs.com,2025-09-06T00:00:00+0000:1757116800</id>
    <updated>2025-09-06T00:00:00+00:00</updated>
    <summary>
      <![CDATA[There are times when you might want to run Laravel Wayfinder automatially without using Vite or Node. Let's take a look at one way to set that up.]]>
    </summary>
    <content type="html">
      <![CDATA[<p>When I am working with Laravel and PHP locally I prefer to use a <a href="https://stagerightlabs.com/blog/starting-a-fresh-laravel-application">docker environment</a> that runs Node and PHP in separate containers. This proved to be a bit challenging with the recent release of <a href="https://github.com/laravel/wayfinder">Laravel Wayfinder</a>, a tool for communicating route definitions between the front-end and the back-end of your application.  The new starter kits now ship with a <a href="https://github.com/laravel/vite-plugin-wayfinder">vite plugin</a> that watches your controller and route files and runs Wayfinder automatically whenever it detects changes to those files.</p>
<p>This strategy works very well and is a fantastic convenience for many local development environments. In my situation, however, my local vite process does not have the ability to trigger php commands due to the separation of concerns in my docker setup.  Fortunately, all is not lost. We can still have the convenience of automated TypeScript route defintions while keeping our container processes separate.  To accomplish this we will set up a script in PHP that will poll for changes to our controllers and route files and then call Wayfinder automatically when they are found.</p>
<ul class="table-of-contents">
<li><a href="#tldr">TLDR</a></li>
<li><a href="#watching-for-changed-files">Watching for changed files</a></li>
<li><a href="#creating-an-entry-point-for-our-container">Creating an entry point for our container</a></li>
<li><a href="#updating-our-php-docker-image">Updating our PHP Docker Image</a></li>
<li><a href="#removing-the-vite-plugin">Removing the Vite plugin</a></li>
</ul>
<h2><a id="tldr" href="#tldr" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>TLDR</h2>
<p>I have set up a <a href="https://gist.github.com/rydurham/7c6c66ea5fe7f4ca2a5d35bb75efcaa2">gist</a> with the scripts I use with my local docker setup.</p>
<h2><a id="watching-for-changed-files" href="#watching-for-changed-files" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Watching for changed files</h2>
<p>To start we will create a method that scans our target directories and returns a list of PHP files to monitor. Here we are using a <code>RecursiveIteratorIterator</code> to wrap a <code>RecursiveDirectoryIterator</code>, an PHP function that reads the contents of directories recursively (both are part of the <a href="https://www.php.net/manual/en/book.spl.php">Standard PHP Library</a>.)  If you are interested in this recursive iterator pattern you can find more information in <a href="https://gbh.fruitbat.io/2024/06/04/php-doing-recursion-with-recursive-iteratoriterators/">this excellent article</a> from Grant Horwood.</p>
<pre data-lang="php" class="notranslate"><span class="hl-keyword">function</span> <span class="hl-property">scan</span>(<span class="hl-injection"><span class="hl-type">array</span> $directory = ['app/Http', 'routes']</span>)
{
    <span class="hl-variable">$files</span> = [];

    <span class="hl-keyword">foreach</span> (<span class="hl-variable">$directory</span> <span class="hl-keyword">as</span> <span class="hl-variable">$dir</span>) {
        <span class="hl-variable">$iterator</span> = <span class="hl-keyword">new</span> <span class="hl-type">RecursiveIteratorIterator</span>(
            <span class="hl-keyword">new</span> <span class="hl-type">RecursiveDirectoryIterator</span>(<span class="hl-variable">$dir</span>)
        );

        <span class="hl-keyword">foreach</span> (<span class="hl-variable">$iterator</span> <span class="hl-keyword">as</span> <span class="hl-variable">$file</span>) {
            <span class="hl-keyword">if</span> (<span class="hl-variable">$file</span>-&gt;<span class="hl-property">isDir</span>() <span class="hl-operator">||</span> <span class="hl-variable">$file</span>-&gt;<span class="hl-property">getExtension</span>() !== <span class="hl-value">'php'</span>) {
                <span class="hl-keyword">continue</span>;
            }
            <span class="hl-variable">$files</span>[<span class="hl-variable">$file</span>-&gt;<span class="hl-property">getPathname</span>()] = <span class="hl-variable">$file</span>-&gt;<span class="hl-property">getMTime</span>();
        }

        <span class="hl-comment">// Free the iterator;</span>
        <span class="hl-keyword">unset</span>(<span class="hl-variable">$iterator</span>);
    }

    <span class="hl-keyword">return</span> <span class="hl-variable">$files</span>;
}
</pre>
<p>Notice that we are returning a list of PHP files associated with their 'last modified' timestamp, which we get from <code>$file-&gt;getMTime()</code>. We can now set up our script to continously poll those files and look for updated timestamps. When we find them we know that the contents of that file has changed and it is time to trigger Wayfinder.  Here is a simplified version of our monitoring loop:</p>
<pre data-lang="php" class="notranslate"><span class="hl-comment">// Our inital directory state </span>
<span class="hl-variable">$timestamps</span> = <span class="hl-property">scan</span>();

<span class="hl-keyword">while</span>(<span class="hl-keyword">true</span>) {
    <span class="hl-variable">$changes</span> = <span class="hl-keyword">false</span>;

    <span class="hl-comment">// Clear PHP's file stat cache</span>
    <span class="hl-property">clearstatcache</span>(<span class="hl-keyword">true</span>);

    <span class="hl-comment">// Get current directory state</span>
    <span class="hl-variable">$files</span> = <span class="hl-property">scan</span>();

    <span class="hl-comment">// Check for new or modified files</span>
    <span class="hl-keyword">foreach</span> (<span class="hl-variable">$files</span> <span class="hl-keyword">as</span> <span class="hl-variable">$path</span> =&gt; <span class="hl-variable">$time</span>) {
        <span class="hl-keyword">if</span> (!<span class="hl-keyword">isset</span>(<span class="hl-variable">$timestamps</span>[<span class="hl-variable">$path</span>])) {
            <span class="hl-variable">$changes</span> = <span class="hl-keyword">true</span>; <span class="hl-comment">// new file </span>
        } <span class="hl-keyword">elseif</span> (<span class="hl-variable">$timestamps</span>[<span class="hl-variable">$path</span>] !== <span class="hl-variable">$mtime</span>) {
            <span class="hl-variable">$changes</span> = <span class="hl-keyword">true</span>; <span class="hl-comment">// modified file</span>
        }
    }

    <span class="hl-comment">// Check for deleted files</span>
    <span class="hl-keyword">foreach</span> (<span class="hl-variable">$timestamps</span> <span class="hl-keyword">as</span> <span class="hl-variable">$path</span> =&gt; <span class="hl-variable">$mtime</span>) {
        <span class="hl-keyword">if</span> (!<span class="hl-keyword">isset</span>(<span class="hl-variable">$files</span>[<span class="hl-variable">$path</span>])) {
            <span class="hl-variable">$changes</span> = <span class="hl-keyword">true</span>; <span class="hl-comment">// file removed</span>
        }
    }

    <span class="hl-comment">// Update our comparisson state</span>
    <span class="hl-variable">$timestamps</span> = <span class="hl-variable">$files</span>;

    <span class="hl-keyword">if</span> (<span class="hl-variable">$changes</span>) {
        <span class="hl-property">runWayfinder</span>();
    }

    <span class="hl-comment">// Memory clenaup</span>
    <span class="hl-keyword">unset</span>(<span class="hl-variable">$files</span>);
    <span class="hl-property">gc_collect_cycles</span>();

    <span class="hl-comment">// Wait 1 second before polling the filesystme again</span>
    <span class="hl-property">sleep</span>(1);
}
</pre>
<p>In this example the <code>runWayfinder()</code> function is a wrapper that uses <code>exec()</code> to trigger the Wayfinder Laravel command. We have also included some manual garbage collection because we don't know how long this script will run and it can't hurt to be extra careful about releasing resources back to the system when they are not needed. I have prepared a gist with a <a href="https://gist.github.com/rydurham/7c6c66ea5fe7f4ca2a5d35bb75efcaa2#file-watch-php">more complete</a> version of this monitoring script.</p>
<h2><a id="creating-an-entry-point-for-our-container" href="#creating-an-entry-point-for-our-container" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Creating an entry point for our container</h2>
<p>We now have a script that will run Wayfinder automatically when we detect changes in the file system. Now we need to set up our PHP docker container to run this script automatically in the background whenever the container starts up. Initially our PHP container was set up to run the artisan <code>serve</code> command as it's default command. To assign multiple tasts to this container we can use an entrypoint script as our primary command and this script will then launch both the Wayfinder monitor as well as the PHP's built-in webserver (via <code>php artisan serve</code>.) This is a simplified example of an entrypoint script:</p>
<pre data-lang="txt" class="notranslate">#!/bin/sh

# Start processes
echo &quot;Starting services...&quot;
php -d display_errors=1 -d error_reporting=E_ALL artisan serve --host 0.0.0.0 --no-ansi -vvv &amp;
php /usr/local/bin/watch.php &amp;

# Wait for any child to exit or signal
trap &quot;exit&quot; SIGTERM SIGINT SIGQUIT TERM; while true; do sleep 1; done
</pre>
<p>In this example we are staring the monitor and the web server in different background processes (note the <code>&amp;</code> at the end of those commands.)  The signal traps at the end allow us to speed up the container shut-down process that occurs when we run <code>docker compose down</code>, not required for our objective but still nice to have.</p>
<h2><a id="updating-our-php-docker-image" href="#updating-our-php-docker-image" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Updating our PHP Docker Image</h2>
<p>Now that we have our monitor script and our entrypoint script we need to update our PHP container to pull in these scripts.  The key part of that change is here:</p>
<pre data-lang="txt" class="notranslate"># .. ignoring the other setup steps for now

# Set the active directory
WORKDIR /var/www

# Copy utility scripts into the container
COPY watch.php /usr/local/bin/
COPY start.sh /usr/local/bin/

# Set the active user
USER ${NAME}

# Set the default command
STOPSIGNAL SIGQUIT
CMD [&quot;/usr/local/bin/start.sh&quot;]
</pre>
<p>Here we are copying our new scripts into the container and running them automatically when the container spins up. With these updates in place we have accomplished our goal and can enjoy the benefits of Wayfinder without needing to combine PHP and Node into a single docker image, which is an ideal solution for my preferred docker setup. Feel free to peruse <a href="https://gist.github.com/rydurham/7c6c66ea5fe7f4ca2a5d35bb75efcaa2">this gist</a> if you want to see the complete version of the scripts I am using for local development.</p>
<h2><a id="removing-the-vite-plugin" href="#removing-the-vite-plugin" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Removing the Vite plugin</h2>
<p>With these scripts in place you can now remove the Wayfinder Vite plugin if you want; just make sure you add a step in your deployment process that calls the Wayfinder artisan command. If you would prefer to use this plugin for deployments you will need to update your <code>vite.config.ts</code> file to ensure that wayfinder only runs in production environments.</p>
]]>
    </content>
    <link rel="alternate" href="https://stagerightlabs.com/blog/automating-wayfinder-without-vite" />
  </entry>
    <entry>
    <title>
      <![CDATA[Starting a Fresh Laravel Application]]>
    </title>
    <id>tag:stagerightlabs.com,2025-01-05T00:00:00+0000:1736035200</id>
    <updated>2025-01-05T00:00:00+00:00</updated>
    <summary>
      <![CDATA[Starting a new project is always an envigorating prospect; so much potential and possiblity, the very world is at your fingertips. It always feels good to start something new. When working on a web projects I prefer to use Laravel, and this article describes how I prepare a brand new project repository.]]>
    </summary>
    <content type="html">
      <![CDATA[<p>Starting a new project is always an envigorating prospect; so much potential and possiblity, the very world is at your fingertips. It always feels good to start something new. When working on a web projects I prefer to use Laravel, and this article describes how I prepare a brand new project repository.</p>
<p>I have created a dedicated <a href="https://github.com/stagerightlabs/fresh-laravel-project">git repo</a> where all of the examples in this article can be referenced. Feel free to clone that repo to start your own project if you don't want to go through all these steps on your own.</p>
<ul class="table-of-contents">
<li><a href="#create-the-new-project">Create the new project</a></li>
<li><a href="#set-up-the-development-environment-with-docker">Set up the development environment with Docker</a>
<ul>
<li><a href="#php">PHP</a></li>
<li><a href="#postgresql">PostgreSQL</a></li>
<li><a href="#node">Node</a></li>
<li><a href="#building-the-environment">Building the Environment</a></li>
</ul>
</li>
<li><a href="#using-vite-for-asset-management">Using Vite for asset management</a></li>
<li><a href="#local-database">Local Database</a></li>
<li><a href="#tests-and-code-coverage">Tests and Code Coverage</a></li>
<li><a href="#static-analysis">Static Analysis</a></li>
<li><a href="#code-formatting">Code Formatting</a></li>
<li><a href="#ops-helper-script">Ops Helper Script</a></li>
</ul>
<h2><a id="create-the-new-project" href="#create-the-new-project" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Create the new project</h2>
<p>Step 1: Use composer to pull down a fresh copy of the Laravel framework. I prefer to use a <a href="https://stagerightlabs.com/blog/utility-containers-for-php">utility container</a> for this as the docker images for the project don't yet exist.</p>
<pre data-lang="txt" class="notranslate">php8.4 composer create-project laravel/laravel starter
cd starter
</pre>
<p>In this case 'starter' is the name of the folder where the code will be placed.</p>
<p>The stack we will be using includes:</p>
<ul>
<li><a href="https://www.php.net/">PHP 8.4</a></li>
<li><a href="https://laravel.com/">Laravel 11</a></li>
<li><a href="https://tailwindcss.com/">Tailwind 3.4</a></li>
<li><a href="https://nodejs.org/">Node 22</a></li>
<li><a href="https://www.postgresql.org/">PostgreSQL 17</a></li>
</ul>
<h2><a id="set-up-the-development-environment-with-docker" href="#set-up-the-development-environment-with-docker" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Set up the development environment with Docker</h2>
<p><a href="https://laravel.com/docs/11.x/sail">Laravel Sail</a> is an excellent tool for managing development environments with Docker, and it is one of the reccomended ways of getting up and running with a new Laravel application. However, I prefer to manage my Docker environment directly using Docker Compose.</p>
<p>We will start with three different services; one each for PHP, PostgreSQL and Node.</p>
<h3><a id="php" href="#php" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>PHP</h3>
<p>The full Dockerfile can be <a href="https://github.com/stagerightlabs/fresh-laravel-project/blob/2025/docker/php/Dockerfile">seen here</a>. The base image is <code>php8.4-alpine</code>; most of the work done in the Dockerfile relates to user permissions and APK dependencies. There are a view items to note however:</p>
<p>The default PHP memory limit is increased to 1096M:</p>
<pre data-lang="dockerfile" class="notranslate"># Increase the default memory limit
<span class="hl-keyword">RUN</span> echo 'memory_limit = 1096M' &gt;&gt; /usr/local/etc/php/conf.d/docker-php-memlimit.ini;
</pre>
<p>Composer is installed for PHP package management:</p>
<pre data-lang="dockerfile" class="notranslate"># Install Composer
<span class="hl-keyword">RUN</span> curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

# Add Composer to the PATH
<span class="hl-keyword">ENV</span> PATH=&quot;$PATH:/usr/local/bin:/home/${NAME}/.composer/vendor/bin&quot;

# Ensure ~/.composer belongs to user
<span class="hl-keyword">RUN</span> mkdir /home/${NAME}/.composer &amp;&amp; chown -R ${NAME}:${NAME} /home/${NAME}
</pre>
<p>Xdebug is installed for step-debugging and code coverage reporting. There is a separate <a href="https://github.com/stagerightlabs/fresh-laravel-project/blob/2025/docker/php/xdebug.ini">xdebug.ini</a> file in the repo containing the xdebug configuration.</p>
<pre data-lang="dockerfile" class="notranslate"># Install XDebug extension for code coverage support
<span class="hl-keyword">RUN</span> pecl install xdebug &amp;&amp; docker-php-ext-enable xdebug
<span class="hl-keyword">COPY</span> xdebug.ini /usr/local/etc/php/conf.d
</pre>
<p>Finally, the container is configured to run <code>php artisan serve</code> automatically when it spins up:</p>
<pre data-lang="dockerfile" class="notranslate"># Serve the web application through the PHP dev server
<span class="hl-keyword">CMD</span> [&quot;php&quot;, &quot;artisan&quot;, &quot;serve&quot;, &quot;--host&quot;, &quot;0.0.0.0&quot;]
</pre>
<h3><a id="postgresql" href="#postgresql" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>PostgreSQL</h3>
<p>The full PostgreSQL docker image can be <a href="https://github.com/stagerightlabs/fresh-laravel-project/blob/2025/docker/postgres/Dockerfile">seen here</a>. Here are a few things to note:</p>
<p>A <a href="https://github.com/stagerightlabs/fresh-laravel-project/blob/2025/docker/postgres/.psqlrc">psqlrc</a> file has been included to configure the PostgreSQL command line tool:</p>
<pre data-lang="dockerfile" class="notranslate"># Copy over the .psqlrc configuration file
<span class="hl-keyword">COPY</span> --chown=postgres:postgres .psqlrc /var/lib/postgresql/
</pre>
<p>An init.sql file has been included to scaffold the new databases:</p>
<pre data-lang="dockerfile" class="notranslate"># Copy our init.sql into the container
# This will only be run if the persistence volume is empty
<span class="hl-keyword">COPY</span> --chown=postgres:postgres init.sql /docker-entrypoint-initdb.d/
</pre>
<p>When the PostgreSQL container spins up it checks to see if there are any known databases present. If not, all of the scripts in the <code>docker-entrypoint-initdb.d</code> folder will be run. In our case, the <code>init.sql</code> file sets up two new databases:</p>
<pre data-lang="sql" class="notranslate"><span class="hl-keyword">CREATE</span> USER developer;
<span class="hl-keyword">ALTER</span> USER developer WITH PASSWORD '<span class="hl-value">secret</span>';

<span class="hl-keyword">CREATE DATABASE</span> app_dev OWNER developer;
GRANT <span class="hl-keyword">ALL</span> PRIVILEGES <span class="hl-keyword">ON</span> <span class="hl-keyword">DATABASE</span> app_dev TO developer;

<span class="hl-keyword">CREATE DATABASE</span> app_test OWNER developer;
GRANT <span class="hl-keyword">ALL</span> PRIVILEGES <span class="hl-keyword">ON</span> <span class="hl-keyword">DATABASE</span> app_test TO developer;
</pre>
<h3><a id="node" href="#node" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Node</h3>
<p>The <a href="https://github.com/stagerightlabs/fresh-laravel-project/blob/2025/docker/node/Dockerfile">node image</a> is very simple. The only modificatioin we make is configuring the image to run <code>yarn dev</code> automatically on startup:</p>
<pre data-lang="dockerfile" class="notranslate"><span class="hl-keyword">CMD</span> [ &quot;yarn&quot;, &quot;dev&quot; ]
</pre>
<h3><a id="building-the-environment" href="#building-the-environment" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Building the Environment</h3>
<p>The <code>docker-compose.yml</code> file is relatively straight forward:</p>
<pre data-lang="yaml" class="notranslate"><span class="hl-keyword">services</span><span class="hl-property">:</span>
    <span class="hl-keyword">php</span><span class="hl-property">:</span>
        <span class="hl-keyword">build</span><span class="hl-property">:</span>
            <span class="hl-keyword">context</span><span class="hl-property">:</span> docker/php
        <span class="hl-keyword">volumes</span><span class="hl-property">:</span>
            <span class="hl-property">-</span> ./:/var/www/:cached
        <span class="hl-keyword">ports</span><span class="hl-property">:</span>
            <span class="hl-property">-</span> <span class="hl-keyword">80</span><span class="hl-property">:</span>8000

    <span class="hl-keyword">postgres</span><span class="hl-property">:</span>
        <span class="hl-keyword">build</span><span class="hl-property">:</span>
            <span class="hl-keyword">context</span><span class="hl-property">:</span> docker/postgres
        <span class="hl-keyword">ports</span><span class="hl-property">:</span>
            <span class="hl-property">-</span> &quot;<span class="hl-value">54320:5432</span>&quot;
        <span class="hl-keyword">environment</span><span class="hl-property">:</span>
            <span class="hl-property">-</span> EDITOR=vim
            <span class="hl-property">-</span> POSTGRES_PASSWORD=secret
        <span class="hl-keyword">volumes</span><span class="hl-property">:</span>
            <span class="hl-property">-</span> <span class="hl-keyword">pg-data</span><span class="hl-property">:</span>/var/lib/postgresql/data
            <span class="hl-property">-</span> ./docker/postgres/<span class="hl-keyword">share</span>:/var/lib/postgresql/share

    <span class="hl-keyword">node</span><span class="hl-property">:</span>
        <span class="hl-keyword">build</span><span class="hl-property">:</span>
            <span class="hl-keyword">context</span><span class="hl-property">:</span> docker/node
        <span class="hl-keyword">volumes</span><span class="hl-property">:</span>
            <span class="hl-property">-</span> ./:/var/<span class="hl-keyword">www</span>:cached
        <span class="hl-keyword">ports</span><span class="hl-property">:</span>
            <span class="hl-property">-</span> <span class="hl-keyword">5173</span><span class="hl-property">:</span>5173

    <span class="hl-keyword">mailpit</span><span class="hl-property">:</span>
        <span class="hl-keyword">image</span><span class="hl-property">:</span> &quot;<span class="hl-value">axllent/mailpit:latest</span>&quot;
        <span class="hl-keyword">ports</span><span class="hl-property">:</span>
            <span class="hl-property">-</span> &quot;<span class="hl-value">${FORWARD_MAILPIT_PORT:-1025}:1025</span>&quot;
            <span class="hl-property">-</span> &quot;<span class="hl-value">${FORWARD_MAILPIT_DASHBOARD_PORT:-8025}:8025</span>&quot;

<span class="hl-keyword">volumes</span><span class="hl-property">:</span>
    <span class="hl-keyword">pg-data</span><span class="hl-property">:</span>
</pre>
<p>I have included a <a href="https://mailpit.axllent.org/">MailPit</a> service as well for testing email locally. With this docker-compose file in place, you can now build the images:</p>
<pre data-lang="txt" class="notranslate">docker compose build
</pre>
<p>To be able to access the site from your browser you may want to add an entry to your local hosts file:</p>
<pre data-lang="txt" class="notranslate">127.0.0.1   starter.test
</pre>
<p>You can spin the containers up now using <code>docker compose up -d</code>, but we don't quite have all of our dependencies in place yet.</p>
<h2><a id="using-vite-for-asset-management" href="#using-vite-for-asset-management" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Using Vite for asset management</h2>
<p>We can now install our node dependencies using the node image. I prefer to use Yarn for package management, but NPM works just as well here.</p>
<pre data-lang="txt" class="notranslate">docker-compose run --rm node yarn
</pre>
<p>There is one small change we need to make to the <a href="https://github.com/stagerightlabs/fresh-laravel-project/blob/2025/vite.config.js">Vite config</a> to get it working in our new docker environment. We will add a &quot;server&quot; block telling vite to use &quot;0.0.0.0&quot; as its default host:</p>
<pre data-lang="js" class="notranslate"><span class="hl-property">server</span>: {
    <span class="hl-property">host</span>: <span class="hl-value">&quot;0.0.0.0&quot;</span>,
    <span class="hl-property">hmr</span>: {
        <span class="hl-property">host</span>: <span class="hl-value">&quot;localhost&quot;</span>,
    },
},
</pre>
<p>With this change in place we can now restart our containers and then view the new site in a web browser: <a href="http://starter.test">http://starter.test</a>. Laravel ships with Tailwind CSS by default, which also happens to be my preferred CSS tool. The default <a href="https://github.com/stagerightlabs/fresh-laravel-project/blob/2025/tailwind.config.js">tailwind.config.js</a> file should be a sufficient starting place.</p>
<h2><a id="local-database" href="#local-database" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Local Database</h2>
<p>We need to tell our new application to use Postgres instead of Sqlite by default. This can be done in our <a href="https://github.com/stagerightlabs/fresh-laravel-project/blob/2025/.env.example">environment file</a>:</p>
<pre data-lang="dotenv" class="notranslate"><span class="hl-keyword">DB_CONNECTION</span>=pgsql
<span class="hl-keyword">DB_HOST</span>=postgres
<span class="hl-keyword">DB_PORT</span>=5432
<span class="hl-keyword">DB_DATABASE</span>=app_dev
<span class="hl-keyword">DB_USERNAME</span>=developer
<span class="hl-keyword">DB_PASSWORD</span>=secret
</pre>
<p>The 'host' value here is the name of the postgres docker service; this is shorthand used by the docker network for service resolution.</p>
<p>Our application database was created automatically when the container spun up for the first time. We can now run our migrations:</p>
<pre data-lang="txt" class="notranslate">docker compose exec php php artisan migrate:fresh
</pre>
<p>A separate database was also created for the testing environment. We will need to update our <a href="https://github.com/stagerightlabs/fresh-laravel-project/blob/2025/phpunit.xml">phpunit.xml</a> file with those details:</p>
<pre data-lang="xml" class="notranslate">&lt;<span class="hl-keyword">php</span>&gt;
    <span class="hl-comment">&lt;!-- other stuff --&gt;</span>
    &lt;<span class="hl-keyword">env</span> <span class="hl-property">name</span>=&quot;DB_CONNECTION&quot; <span class="hl-property">value</span>=&quot;pgsql&quot;/&gt;
    &lt;<span class="hl-keyword">env</span> <span class="hl-property">name</span>=&quot;DB_HOST&quot; <span class="hl-property">value</span>=&quot;postgres&quot;/&gt;
    &lt;<span class="hl-keyword">env</span> <span class="hl-property">name</span>=&quot;DB_DATABASE&quot; <span class="hl-property">value</span>=&quot;app_dev&quot;/&gt;
    &lt;<span class="hl-keyword">env</span> <span class="hl-property">name</span>=&quot;DB_USERNAME&quot; <span class="hl-property">value</span>=&quot;developer&quot;/&gt;
    &lt;<span class="hl-keyword">env</span> <span class="hl-property">name</span>=&quot;DB_SECRET&quot; <span class="hl-property">value</span>=&quot;secret&quot;/&gt;
    <span class="hl-comment">&lt;!-- other stuff --&gt;</span>
&lt;/<span class="hl-keyword">php</span>&gt;
</pre>
<h2><a id="tests-and-code-coverage" href="#tests-and-code-coverage" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Tests and Code Coverage</h2>
<p>With the xdebug extension installed we can configure PHPUnit to generate code coverage reports for us. We do this by adding a <code>&lt;coverage&gt;</code> block to the <a href="https://github.com/stagerightlabs/fresh-laravel-project/blob/2025/phpunit.xml">phpunit.xml</a> file:</p>
<pre data-lang="xml" class="notranslate">&lt;<span class="hl-keyword">coverage</span>&gt;
    &lt;<span class="hl-keyword">report</span>&gt;
        &lt;<span class="hl-keyword">html</span> <span class="hl-property">outputDirectory</span>=&quot;.coverage&quot; <span class="hl-property">lowUpperBound</span>=&quot;50&quot; <span class="hl-property">highLowerBound</span>=&quot;90&quot;/&gt;
    &lt;/<span class="hl-keyword">report</span>&gt;
&lt;/<span class="hl-keyword">coverage</span>&gt;
</pre>
<p>The output directory can be whatever you would like; just make sure to add it to your git ignore file.</p>
<p>Composer offers the ability to run scripts for us, similar to NPM and Yarn. I prefer to use this method for running the test suite. To do this we will add a new entry in the <code>scripts</code> section of the <a href="https://github.com/stagerightlabs/fresh-laravel-project/blob/2025/composer.json">composer.json</a> file:</p>
<pre data-lang="js" class="notranslate"><span class="hl-value">&quot;scripts&quot;</span>: {
    <span class="hl-comment">// ...</span>
    <span class="hl-value">&quot;test&quot;</span>: <span class="hl-value">&quot;vendor/bin/phpunit&quot;</span>
},
</pre>
<h2><a id="static-analysis" href="#static-analysis" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Static Analysis</h2>
<p><a href="https://phpstan.org/">PHPStan</a> is my preferred static analysis tool; and the <a href="https://github.com/larastan/larastan">Larastan</a> project provides an excellent way to integrate static analysis into a Laravel application.</p>
<p>We will first add Larastan as a composer dependency:</p>
<pre data-lang="txt" class="notranslate">docker compose exec php composer require --dev &quot;larastan/larastan:^3.0&quot;
</pre>
<p>Adding a <a href="https://github.com/stagerightlabs/fresh-laravel-project/blob/2025/phpstan.neon">phpstan.neon</a> file to the root of the project allows us to configure PHPStan for this application. I personally strive for level 8 in all of my projects.</p>
<p>We can again use a composer script for running static analysis:</p>
<pre data-lang="js" class="notranslate"><span class="hl-value">&quot;scripts&quot;</span>: {
    <span class="hl-comment">// ...</span>
    <span class="hl-value">&quot;phpstan&quot;</span>: <span class="hl-value">&quot;phpstan analyze&quot;</span>
},
</pre>
<h2><a id="code-formatting" href="#code-formatting" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Code Formatting</h2>
<p>Laravel ships with a tool called <a href="https://laravel.com/docs/11.x/pint">Pint</a> that performs PHP code formatting. Pint is a wrapper for the excellent <code>friendsofphp/php-cs-fixer</code> tool. We will set it up for this project using the &quot;per&quot; standard, which is the latest successor to the &quot;psr-12&quot; standard. We will also use composer to run our formatting for us:</p>
<pre data-lang="js" class="notranslate"><span class="hl-value">&quot;scripts&quot;</span>: {
    <span class="hl-comment">// ...</span>
     <span class="hl-value">&quot;format&quot;</span>: <span class="hl-value">&quot;pint --preset per&quot;</span>,
},
</pre>
<p>I like to use Prettier for formatting JavaScript and Blade files. It can also automatically sort tailwind classes for us which is a nice bonus. Matt Stauffer has an <a href="https://mattstauffer.com/blog/how-to-set-up-prettier-on-a-laravel-app-to-lint-tailwind-class-order-and-more/">excellent post</a> on his blog that details setting up Prettier for Laravel. The VSCode Prettier plugin will automatically run this formatting for us. We don't necessarily need to add a script to run it manually but we could by updating the &quot;scripts&quot; block in the <a href="https://github.com/stagerightlabs/fresh-laravel-project/blob/2025/package.json">package.json</a> file:</p>
<pre data-lang="js" class="notranslate"><span class="hl-value">&quot;scripts&quot;</span>: {
    <span class="hl-comment">// ...</span>
    <span class="hl-value">&quot;format&quot;</span>: <span class="hl-value">&quot;prettier . --write&quot;</span>
},
</pre>
<h2><a id="ops-helper-script" href="#ops-helper-script" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Ops Helper Script</h2>
<p>To streamline local development tasks I like to set up an <a href="https://github.com/stagerightlabs/fresh-laravel-project/blob/2025/ops.sh">ops helper script</a>. This is an idea that I borrowed from Chris Fidao and his <a href="https://serversforhackers.com/shipping-docker">Shipping Docker</a> course. It becomes super helpful when combined with a bash alias:</p>
<pre data-lang="txt" class="notranslate">starter() {
    cd /full/path/to/project
    ./ops.sh ${*:-ps}
    cd $OLDPWD
}
</pre>
<p>You can call the function whatever you would like. With this alias in place you can now easily run development tasks without having to spell out the full docker command each time:</p>
<pre data-lang="txt" class="notranslate">starter artisan make:model Team -mfs # Make a new model with a migration, factory and seeder
starter composer require [package] # Add a PHP package with Composer
starter composer format # Run Laravel Pint to format PHP code
starter composer phpstan # Run PHPStan for static analysis
starter composer test # Run the test suite
starter psql app_dev # Drop into the postgres cli for the app_dev database
starter yarn add [package] # Add a node dependency with Yarn
starter yarn format # Run a yarn script
</pre>
<p>This script is easily extendible if you add more services to the docker environment.</p>
]]>
    </content>
    <link rel="alternate" href="https://stagerightlabs.com/blog/starting-a-fresh-laravel-application" />
  </entry>
    <entry>
    <title>
      <![CDATA[Utility Containers for PHP]]>
    </title>
    <id>tag:stagerightlabs.com,2024-12-28T00:00:00+0000:1735344000</id>
    <updated>2024-12-28T00:00:00+00:00</updated>
    <summary>
      <![CDATA[Leverage bash functions and docker containers to allow quick access to tools like PHP and Node without installing them locally.]]>
    </summary>
    <content type="html">
      <![CDATA[<p>I have found that after using Docker for a while the idea of installing programming libraries directly on my development machine undesirable; my preference is to use Docker for everything I can and keep the host machine as clean as possible. However, there are still times when having quick access to node or to PHP can be handy, and when those tools are not installed I feel friction in my productivity flow.</p>
<p>I have found that I can still use Docker for these situations by leveraging bash functions to make access to those containers smoother. This combination has become a productivity booster for me; it turns out to be very convenient.</p>
<p>As an added bonus, this technique let's me easily access different versions of PHP and Node on the same machine without bothering with NVM or switching between multiple PHP installs.</p>
<ul class="table-of-contents">
<li><a href="#docker-container">Docker Container</a></li>
<li><a href="#bash-function">Bash Function</a></li>
<li><a href="#usage">Usage</a></li>
<li><a href="#node">Node</a></li>
</ul>
<h2><a id="docker-container" href="#docker-container" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Docker Container</h2>
<p>First you will need an image containing the tool you want to run. If you are feeling adventurous you could build this yourself, or you could use one of the many images availably publicly on <a href="hub.docker.com">hub.docker.com</a>. For PHP I reccomend finding an image that has Composer already installed, as well as some of the more commonly used extensions such as BCMath and Zip. The <a href="https://kirschbaumdevelopment.com/">Kirschbaum Development Group</a> maintains a <a href="https://hub.docker.com/r/kirschbaumdevelopment/laravel-test-runner">PHP image</a> for use in continuous integration tools; this could be an ideal jumping off point for you.</p>
<p>One of the great benefits of Docker is its flexibilty. I started out with the Kirschbaum image but eventually needed to make my own modifications. I have published <a href="https://hub.docker.com/r/stagerightlabs/php-test-runner">my own verison</a> of a &quot;test runner&quot; image. These image variants are customized for my particular needs; you can extend existing images or build your own as needed.</p>
<h2><a id="bash-function" href="#bash-function" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Bash Function</h2>
<p>Now that you have identified the container you want to use, add this function to your bash config:</p>
<pre data-lang="txt" class="notranslate">php8.3() {
    docker run -it --rm \
    -u 1000 \
    -e COMPOSER_HOME=/home/www-data/.config/composer \
    -v $(pwd):/var/www \
    -w /var/www \
    -p 8000:8000 \
    stagerightlabs/php-test-runner:8.3 /bin/sh -c &quot;${*:-sh}&quot;
}
</pre>
<p>You can name the function whatever you would like. Let's run down the parameters:</p>
<ol>
<li><code>docker run -it --rm</code>: This tells docker that you want to run a container with an interactive shell and then automatically shut it down when the command is finsished.</li>
<li><code>-u 1000</code>: This sets the user id for the container session. If your host machine is running linux this will allow you to avoid problems with permissions on files created in the image. The number should match your user id on the host machine. On Ubuntu the default user is UID 1000.</li>
<li><code>-e COMPOSER_HOME=/home/www-data/.config/composer</code>: This sets an environment variable in the container that tells Composer to use a custom home folder; in this case the UID user, aka &quot;www-data&quot; in this image. This ensures that all of Composer's cache files will be owned by the UID 1000 user to avoid more file permissions issues.</li>
<li><code>-v $(pwd):/var/www</code>: This mounts the current working director on the host machine as a volume in Docker at the <code>/var/www</code> location.</li>
<li><code>-w /var/www</code>: This sets <code>/var/www</code> as the current working directory for the container.</li>
<li><code>-p 8000:8000</code>: This maps port 8000 in the container to port 8000 on the host machine. This is not strictly necessary, but you might find port mapping like this convenient, depending on your needs.</li>
<li><code>stagerightlabs/php-test-runner:8.3</code>: This is the name of the container we are going to spin up.</li>
<li><code>/bin/sh -c &quot;${*:-sh}&quot;</code>: This tells the container to execute a shell command. It will pass in any command line arguments you provide, or if none are provided it will drop you into a shell session.</li>
</ol>
<h2><a id="usage" href="#usage" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Usage</h2>
<p>With this function in place you can now run PHP commands anywhere on your machine without installing PHP natively:</p>
<pre data-lang="txt" class="notranslate">~/code/project $ php8.3 composer create-project laravel/laravel .
</pre>
<p>I find it particularly helpful when I am working on package development and I want to run tests or other composer commands:</p>
<pre data-lang="txt" class="notranslate">~/code/package $ php8.3 vendor/bin/phpunit
~/code/package $ php8.3 composer require laravel/tinker
~/code/package $ php8.3 composer [some custom script]
</pre>
<p>This way I don't need to set up a dedicated image for the package and I can save on some of that overhead.</p>
<p>You can also execute PHP commands directly:</p>
<pre data-lang="txt" class="notranslate">~ $ php8.3 php path/to/script.php
Output of the script...
~ $ php8.3 php -version
PHP 8.3.3 (cli) (built: Feb 16 2024 21:25:21) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.3.3, Copyright (c) Zend Technologies
    with Xdebug v3.3.1, Copyright (c) 2002-2023, by Derick Rethans
</pre>
<h2><a id="node" href="#node" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Node</h2>
<p>This idea works with many different tools. I find it to be a very handy way to use Node and NPM:</p>
<pre data-lang="txt" class="notranslate">node20() {
    docker run -it --rm -u 1000 -v $(pwd):/src node:20-alpine /bin/sh -c &quot;cd /src; ${*:-sh}&quot;
}
</pre>
<p>It may take a bit of work to dial in the configuration for the image you are using, but the payoff will be worth it.</p>
]]>
    </content>
    <link rel="alternate" href="https://stagerightlabs.com/blog/utility-containers-for-php" />
  </entry>
    <entry>
    <title>
      <![CDATA[Adjusting Security Headers in Laravel]]>
    </title>
    <id>tag:stagerightlabs.com,2024-12-21T00:00:00+0000:1734739200</id>
    <updated>2024-12-21T00:00:00+00:00</updated>
    <summary>
      <![CDATA[Certain important security headers are not set by default in a fresh Laravel application. We will use a middleware class to add them to an application.]]>
    </summary>
    <content type="html">
      <![CDATA[<p>If you check the security headers of a fresh Laravel application using a tool like <a href="https://securityheaders.com">securityheaders.com</a> you will notice that a few important headers are not set by default:</p>
<p>These are left to developers to implement because each application will have different needs. To add these headers we will set up a middleware to ensure the headers are set on a response when it leaves the server.</p>
<ul class="table-of-contents">
<li><a href="#creating-a-middleware">Creating a Middleware</a></li>
<li><a href="#adding-security-headers">Adding Security Headers</a></li>
<li><a href="#resources">Resources</a></li>
</ul>
<h2><a id="creating-a-middleware" href="#creating-a-middleware" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Creating a Middleware</h2>
<p>We can make a new middleware class using artisan:</p>
<pre data-lang="txt" class="notranslate">$ php artisan make:middleware SetSecurityHeaders
</pre>
<p>You can then register that middleware class in the <code>bootstrap/app.php</code> file:</p>
<pre data-lang="php" class="notranslate"><span class="hl-keyword">return</span> <span class="hl-type">Application</span>::<span class="hl-property">configure</span>(<span class="hl-property">basePath</span>: <span class="hl-property">dirname</span>(<span class="hl-property">__DIR__</span>))
    <span class="hl-comment">// ...</span>
    -&gt;<span class="hl-property">withMiddleware</span>(<span class="hl-keyword">function</span> (<span class="hl-injection"><span class="hl-type">Middleware</span> $middleware</span>) {
        <span class="hl-variable">$middleware</span>-&gt;<span class="hl-property">web</span>(<span class="hl-property">append</span>: [<span class="hl-type">SetSecurityHeaders</span>::<span class="hl-keyword">class</span>]);
    })
    <span class="hl-comment">// ...</span>
</pre>
<p>In this example we are adding the <code>SetSecurityHeaders</code> middleware to the <code>web</code> middleware group; but you could also choose to only assign this middleware to specific routes if needed.</p>
<h2><a id="adding-security-headers" href="#adding-security-headers" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Adding Security Headers</h2>
<p>Let's now update out middelware to set the security headers we want to add:</p>
<pre data-lang="php" class="notranslate"><span class="hl-keyword">public</span> <span class="hl-keyword">function</span> <span class="hl-property">handle</span>(<span class="hl-injection"><span class="hl-type">Request</span> $request, <span class="hl-type">Closure</span> $next</span>): <span class="hl-type">Response</span>
{
    <span class="hl-type">Vite</span>::<span class="hl-property">useCspNonce</span>();
    <span class="hl-variable">$response</span> = <span class="hl-variable">$next</span>(<span class="hl-variable">$request</span>);

    <span class="hl-comment">// We will only apply these headers in production</span>
    <span class="hl-keyword">if</span> (<span class="hl-property">app</span>()-&gt;<span class="hl-property">environment</span>(<span class="hl-value">'local'</span>)) {
        <span class="hl-keyword">return</span> <span class="hl-variable">$response</span>;
    }

    <span class="hl-comment">// Strict Transport Security</span>
    <span class="hl-comment">// https://scotthelme.co.uk/hsts-the-missing-link-in-tls/</span>
    <span class="hl-comment">// https://securinglaravel.com/security-tip-how-strict-is-your-transport-security/</span>
    <span class="hl-variable">$response</span>-&gt;<span class="hl-property">headers</span>-&gt;<span class="hl-keyword">set</span>(
        <span class="hl-value">'Strict-Transport-Security'</span>,
        <span class="hl-value">'max-age=31536000; includeSubDomains'</span>,
        <span class="hl-variable">$replace</span> = <span class="hl-keyword">true</span>
    );

    <span class="hl-comment">// Content Security Policy</span>
    <span class="hl-comment">// https://scotthelme.co.uk/content-security-policy-an-introduction/</span>
    <span class="hl-comment">// https://securinglaravel.com/security-tip-getting-started-with-csp/</span>
    <span class="hl-variable">$response</span>-&gt;<span class="hl-property">headers</span>-&gt;<span class="hl-keyword">set</span>(
        <span class="hl-value">'Content-Security-Policy'</span>,
        <span class="hl-value">&quot;script-src 'nonce-&quot;</span>.<span class="hl-type">Vite</span>::<span class="hl-property">cspNonce</span>().<span class="hl-value">&quot;' 'strict-dynamic'; object-src 'none'; base-uri 'none'; require-trusted-types-for 'script';&quot;</span>
        <span class="hl-variable">$replace</span> = <span class="hl-keyword">true</span>,
    );

    <span class="hl-comment">// Referrer Policy</span>
    <span class="hl-comment">// https://scotthelme.co.uk/a-new-security-header-referrer-policy/</span>
    <span class="hl-comment">// https://securinglaravel.com/security-tip-is-your-referrer-leaking-information/</span>
    <span class="hl-variable">$response</span>-&gt;<span class="hl-property">headers</span>-&gt;<span class="hl-keyword">set</span>(
        <span class="hl-value">'Referrer-Policy'</span>,
        <span class="hl-value">'strict-origin'</span>,
        <span class="hl-variable">$replace</span> = <span class="hl-keyword">true</span>,
    );

    <span class="hl-comment">// Permissions Policy</span>
    <span class="hl-comment">// https://scotthelme.co.uk/goodbye-feature-policy-and-hello-permissions-policy/</span>
    <span class="hl-comment">// https://securinglaravel.com/security-tip-do-you-have-a-permissions-policy/</span>
    <span class="hl-variable">$response</span>-&gt;<span class="hl-property">headers</span>-&gt;<span class="hl-keyword">set</span>(
        <span class="hl-value">'Permissions-Policy'</span>,
        <span class="hl-value">&quot;autoplay=(), battery=(), cross-origin-isolated=(), execution-while-not-rendered=()&quot;</span>,
        <span class="hl-variable">$replace</span> = <span class="hl-keyword">true</span>,
    );

    <span class="hl-keyword">return</span> <span class="hl-variable">$response</span>;
}
</pre>
<p>The values listed here are just an example; you will need to tailor these policies to the needs of your application.</p>
<p>Note that we call <code>$response = $next($request);</code> first; this ensures that our header changes are applied to the response after the rest of the application has finished its work. You can see also that we are passing in <code>true</code> as the third parameter of <code>$response-&gt;headers-&gt;set()</code> this will ensure that any previous values for those headers will be replaced with these new values.</p>
<p>We are also using Vite to manage nonce values for the content security policy; these will automatically be refreshed on every request.</p>
<h2><a id="resources" href="#resources" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Resources</h2>
<ul>
<li><a href="https://securinglaravel.com/security-tip-security-headers-are/">Securing Laravel</a></li>
<li><a href="https://laravel.com/docs/11.x/vite#content-security-policy-csp-nonce">Larave Vite CSP Nonce</a></li>
<li><a href="https://securityheaders.com">Security Headers</a></li>
<li><a href="https://www.permissionspolicy.com/">Permissions Policy Header Generator</a></li>
<li><a href="https://csp-evaluator.withgoogle.com/">Google Content Security Policy Evaluator</a></li>
</ul>
]]>
    </content>
    <link rel="alternate" href="https://stagerightlabs.com/blog/adjusting-security-headers-in-laravel" />
  </entry>
    <entry>
    <title>
      <![CDATA[Adding Sqids to a Laravel Application]]>
    </title>
    <id>tag:stagerightlabs.com,2023-12-02T00:00:00+0000:1701475200</id>
    <updated>2023-12-02T00:00:00+00:00</updated>
    <summary>
      <![CDATA[Sqids is a revised version of Hashids; lets explore using it to obfuscate model Ids in Laravel.]]>
    </summary>
    <content type="html">
      <![CDATA[<p>When constructing a URL for a model resource in a standard Laravel application there are really only two options for unique identifiers: model Ids and slugs. UUIDs are also a possibility but they require some extra configuration so I don't consider them a 'standard' option. Model Ids are convenient but you might not want to expose primary keys to your users, for myriad reasons. It is often the case that slugs are not feasible for certain types of model. Our best bet then is to somehow obfuscate model Ids for the sake of generating resource URLs. This will make it much less obvious how many users are in our database, or how many invoices we have sent. Obfuscation like this is possible but requires a bit of work to integrate with a Laravel application.</p>
<p>For a long time, the best option was a library called <a href="https://packagist.org/packages/hashids/hashids">Hashids</a>, which also has a <a href="https://packagist.org/packages/vinkla/hashids">Laravel bridge package</a> created by Vincent Klaiber. Recently, however the Hashids project announced the launch of a new tool called <a href="https://sqids.org">Sqids</a>; the spiritual successor to Hashids. This is more than just a rebranding: the underlying algorithm has been simplified and is now Identical across all platforms. A <a href="https://github.com/sqids/sqids-php">PHP implementation</a> was recently released, created by Ivan Akimov and Vincent Klaiber.</p>
<p>Let's take a look at how we can integrate Sqids with a Laravel application. Our goal will be to allow this integration to be completely transparent with our usage of the framework.</p>
<p>NB: Sqids can be decoded by third parties so they are not good for truly sensitive information. If that is a concern for your application you should consider <a href="https://packagist.org/packages/jenssegers/optimus">an alternative stragey</a>.</p>
<ul class="table-of-contents">
<li><a href="#getting-started">Getting Started</a></li>
<li><a href="#configuration">Configuration</a></li>
<li><a href="#model-accessor">Model Accessor</a></li>
<li><a href="#route-model-binding">Route Model Binding</a></li>
</ul>
<h2><a id="getting-started" href="#getting-started" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Getting Started</h2>
<p>First we will pull in the <code>sqids/sqids-php</code> package with Composer:</p>
<pre data-lang="txt" class="notranslate">composer require sqids/sqids
</pre>
<p>NB: <code>sqids/sqids-php</code> requires at least PHP 8.1 and either ext-bcmath or ext-gmp; it has no other dependencies.</p>
<p>Now we will set up a utility class to handle encoding and decoding sqids:</p>
<pre data-lang="php" class="notranslate"><span class="hl-keyword">&lt;?php</span>

<span class="hl-keyword">namespace</span> <span class="hl-type">App\Utility</span>;

<span class="hl-keyword">use</span> <span class="hl-type">Sqids\Sqids</span>;

<span class="hl-keyword">final</span> <span class="hl-keyword">class</span> <span class="hl-type">Sqid</span>
{
  <span class="hl-comment">/**
   * Encode an integer as a hashid.
   */</span>
  <span class="hl-keyword">public</span> <span class="hl-keyword">static</span> <span class="hl-keyword">function</span> <span class="hl-property">encode</span>(<span class="hl-injection"><span class="hl-type">?int</span> $number</span>): <span class="hl-type">string</span>
  {
    <span class="hl-keyword">if</span> (<span class="hl-property">is_null</span>(<span class="hl-variable">$number</span>)) {
      <span class="hl-keyword">return</span> <span class="hl-value">''</span>;
    }

    <span class="hl-keyword">return</span> <span class="hl-property">resolve</span>(<span class="hl-type">Sqids</span>::<span class="hl-keyword">class</span>)-&gt;<span class="hl-property">encode</span>([<span class="hl-variable">$number</span>]);
  }

  <span class="hl-comment">/**
   * Decode a sqid string into an integer.
   */</span>
  <span class="hl-keyword">public</span> <span class="hl-keyword">static</span> <span class="hl-keyword">function</span> <span class="hl-property">decode</span>(<span class="hl-injection"><span class="hl-type">string</span> $sqid</span>): <span class="hl-type">int</span>
  {
    <span class="hl-keyword">return</span> <span class="hl-property">resolve</span>(<span class="hl-type">Sqids</span>::<span class="hl-keyword">class</span>)-&gt;<span class="hl-property">decode</span>(<span class="hl-variable">$sqid</span>)[0];
  }
}
</pre>
<p>Squids is built to handle arrays; it accepts an array of integers for encoding and returns an array of integers when decoding. In our case we are only interested in single integer values, not arrays, so the utility methods above handles packaging and unpacking the arrays for us. The <code>resolve()</code> method is a Laravel tool for fetching classes from the service container.</p>
<p>One nice benefit of Sqids over Hashids is that there is no need for a salt value to randomize the output. It works out of the box without any additional configuration, which may suit your needs just fine. In my case, however, I would like to ensure that all of the generated sqid strings have the same minimum length for the lifetime of my application. This can be achieved by passing in a <code>minLength</code> value to the constructor:</p>
<pre data-lang="php" class="notranslate">(<span class="hl-keyword">new</span> <span class="hl-type">Sqids</span>(<span class="hl-property">minLength</span>: 6))-&gt;<span class="hl-property">encode</span>([1]);
<span class="hl-comment">// 'UkLWZg'</span>
</pre>
<p>NB: This is a <em>minimum</em> length, not a specific length.</p>
<p>Additionally, the default &quot;alphabet&quot; of characters used for generating sqid strings contains uppercase and lowercase letters together. I would prefer to use only lowercase letters so I don't have to be concerned about handling case-sensitive URLs.</p>
<p>To achieve these goals we will prepare an instance of the Sqids class that is configured to our liking and bind it to the service container as a singleton so we can resolve it wherever we need it.</p>
<h2><a id="configuration" href="#configuration" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Configuration</h2>
<p>Let's create a new service provider to handle our Sqids configuration:</p>
<pre data-lang="txt" class="notranslate">php artisan make:provider SqidsServiceProvider
</pre>
<p>This will create a new <code>app/Providers/SqidsServiceProvider</code> class. We will use the <code>register</code> method to handle our configuration:</p>
<pre data-lang="php" class="notranslate"><span class="hl-keyword">&lt;?php</span>

<span class="hl-keyword">namespace</span> <span class="hl-type">App\Providers</span>;

<span class="hl-keyword">use</span> <span class="hl-type">Illuminate\Support\ServiceProvider</span>;
<span class="hl-keyword">use</span> <span class="hl-type">Sqids\Sqids</span>;

<span class="hl-keyword">class</span> <span class="hl-type">SqidsServiceProvider</span> <span class="hl-keyword">extends</span> <span class="hl-type">ServiceProvider</span>
{
  <span class="hl-keyword">const</span> <span class="hl-property">PAD</span> = 7;
  <span class="hl-keyword">const</span> <span class="hl-property">ALPHABET</span> = <span class="hl-value">'msd793zjyw5rf8v6qxahpgn1bk0etc4u2'</span>;

  <span class="hl-comment">/**
   * Register services.
   */</span>
  <span class="hl-keyword">public</span> <span class="hl-keyword">function</span> <span class="hl-property">register</span>(): <span class="hl-type">void</span>
  {
    <span class="hl-variable">$this</span>-&gt;<span class="hl-property">app</span>-&gt;<span class="hl-property">singleton</span>(<span class="hl-type">Sqids</span>::<span class="hl-keyword">class</span>, <span class="hl-keyword">function</span> () {
      <span class="hl-keyword">return</span> <span class="hl-keyword">new</span> <span class="hl-type">Sqids</span>(<span class="hl-type">self</span>::<span class="hl-property">ALPHABET</span>, <span class="hl-type">self</span>::<span class="hl-property">PAD</span>);
    });
  }
}
</pre>
<p>In addition to shortening the alphabet I have also shuffled the order of the letters. This is the recommended method for generating sqid values that are unique to your application. I have also removed the letters 'l', 'i' and 'o' because they look similar to '1' and '0', though you can craft any alphabet you would like.</p>
<p>Make sure you <a href="https://laravel.com/docs/10.x/providers#registering-providers">register</a> your provider in your <code>config/app.php</code> file. With this singleton bound to the service container we are guaranteed to get our configured version of the Squids class any time we resolve it through the container:</p>
<pre data-lang="php" class="notranslate"><span class="hl-variable">$sqid</span> = <span class="hl-property">resolve</span>(<span class="hl-type">Sqids</span>::<span class="hl-keyword">class</span>)-&gt;<span class="hl-property">encode</span>([<span class="hl-variable">$number</span>]);
</pre>
<h2><a id="model-accessor" href="#model-accessor" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Model Accessor</h2>
<p>Rather than having to encode a model Id every time we need to reference a sqid, we can use a model accessor to compute sqids automatically. We will set this up as a trait that can be applied to any model that want to reference with sqids:</p>
<pre data-lang="php" class="notranslate"><span class="hl-keyword">&lt;?php</span>

<span class="hl-keyword">namespace</span> <span class="hl-type">App\Models</span>;

<span class="hl-keyword">use</span> <span class="hl-type">App\Utility\Sqid</span>;
<span class="hl-keyword">use</span> <span class="hl-type">Illuminate\Database\Eloquent\Casts\Attribute</span>;

<span class="hl-keyword">trait</span> <span class="hl-type">HasSqid</span>
{
  <span class="hl-comment">/**
   * Get the obfuscated version of the model Id.
   *
   * <span class="hl-value">@see</span> https://sqids.org
   */</span>
  <span class="hl-keyword">protected</span> <span class="hl-keyword">function</span> <span class="hl-property">sqid</span>(): <span class="hl-type">Attribute</span>
  {
    <span class="hl-keyword">return</span> <span class="hl-type">Attribute</span>::<span class="hl-property">make</span>(
      <span class="hl-property">get</span>: <span class="hl-keyword">fn</span> () =&gt; <span class="hl-type">Sqid</span>::<span class="hl-property">encode</span>(<span class="hl-variable">$this</span>-&gt;<span class="hl-property">id</span>)
    );
  }
}
</pre>
<p>NB: I have put this trait in the <code>App\Models</code> namespace but you can put it anywhere you want, just make sure to adjust line 3.</p>
<p>Now when we call <code>$model-&gt;sqid</code> we will get the appropriate sqid version of the model Id based on our configuration specs from earlier.</p>
<p>The last piece of the puzzle is <a href="https://laravel.com/docs/10.x/routing#route-model-binding">route model binding</a>. Can we get Laravel to translate sqids into models for us automatically when handling routes? Let's give it a shot.</p>
<h2><a id="route-model-binding" href="#route-model-binding" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Route Model Binding</h2>
<p>We will add two additional methods to our <code>HasSqid</code> trait:</p>
<pre data-lang="php" class="notranslate"><span class="hl-comment">/**
 * Get the route key for the model.
 *
 * <span class="hl-value">@return</span> <span class="hl-type">string</span>
 */</span>
<span class="hl-keyword">public</span> <span class="hl-keyword">function</span> <span class="hl-property">getRouteKeyName</span>()
{
  <span class="hl-keyword">return</span> <span class="hl-value">'sqid'</span>;
}
</pre>
<p>This method tells Laravel to use the 'sqid' accessor when generating model routes instead of 'id':</p>
<pre data-lang="php" class="notranslate"><span class="hl-property">route</span>(<span class="hl-value">'some.named.route'</span>, <span class="hl-variable">$sqidModel</span>);
<span class="hl-comment">// https://myapp.com/some/named/route/abc1234</span>
</pre>
<p>Next, we will intercept the route model binding handler to decode the sqid before querying the database:</p>
<pre data-lang="php" class="notranslate"><span class="hl-comment">/**
 * Retrieve the model for a bound value.
 *
 * <span class="hl-value">@param</span> <span class="hl-type">mixed</span> <span class="hl-variable">$value</span>
 * <span class="hl-value">@param</span> <span class="hl-type">string|null</span> <span class="hl-variable">$field</span>
 * <span class="hl-value">@return</span> <span class="hl-type">\Illuminate\Database\Eloquent\Model|null</span>
 */</span>
<span class="hl-keyword">public</span> <span class="hl-keyword">function</span> <span class="hl-property">resolveRouteBinding</span>(<span class="hl-injection">$value, $field = <span class="hl-keyword">null</span></span>)
{
  <span class="hl-keyword">return</span> <span class="hl-variable">$this</span>-&gt;<span class="hl-property">resolveRouteBindingQuery</span>(<span class="hl-variable">$this</span>, <span class="hl-type">Sqid</span>::<span class="hl-property">decode</span>(<span class="hl-variable">$value</span>), <span class="hl-value">'id'</span>)-&gt;<span class="hl-property">first</span>();
}
</pre>
<p>The &quot;value&quot; passed into <code>resolveRouteBinding</code> method is the sqid string itself. The &quot;field&quot; is not necessary for our purposes but it relates to <a href="https://laravel.com/docs/10.x/routing#customizing-the-key">optional key customization</a>. In our version of the <code>resolveRouteBinding</code> method we are telling Eloquent to find the first database record that has an Id that matches our decoded sqid value.</p>
<p>With those two methods in place we can now add this trait to any model we want and automatically enable the use of sqids for that model and Laravel does all of the heaving lifting for us automatically. Perfect!</p>
<p>Having been a big fan of Hashids for several years now it was delightful to see this new simplified and upgraded version released recently. Ivan and Vincent have done an excellent job on this PHP implementation.</p>
]]>
    </content>
    <link rel="alternate" href="https://stagerightlabs.com/blog/adding-sqids-to-a-laravel-application" />
  </entry>
    <entry>
    <title>
      <![CDATA[Asset Versioning in Laravel]]>
    </title>
    <id>tag:stagerightlabs.com,2021-03-23T00:00:00+0000:1616457600</id>
    <updated>2021-03-23T00:00:00+00:00</updated>
    <summary>
      <![CDATA[Asset versioning helps us ensure that browsers will always use the latest version of our compiled assets when they visit our site. Let's take a look at a strategy for asset versioning in Laravel.]]>
    </summary>
    <content type="html">
      <![CDATA[<p>Laravel Mix provides an asset versioning tool that allows us to ensure that browsers are always pulling in the latest version of our compiled assets. How can we implement cache busting <a href="https://stagerightlabs.com/blog/you-might-not-need-laravel-mix">if we are not using Laravel Mix</a>? Here is a strategy that I have found useful.</p>
<p>The key to forcing browsers to update their asset cache is to change the name of the file that is being referenced. Laravel Mix does this by implementing asset fingerprinting; a unique file name is generated for each asset each time you run your mix scripts (in production) and the <code>mix()</code> helper method looks up the appropriate name via a <code>mix-manifest.json</code> file that is stored in your public path.</p>
<p>We can accomplish something similar by appending a query string parameter to our asset URLs. To do that we will set up a config value to keep track of our asset version and then use that value as a query parameter when calling our asset files.</p>
<p>To implement this we will first create an <code>assets.php</code> config file in our <code>config/</code> directory. This config file will have one value, called &quot;version&quot;:</p>
<ul class="table-of-contents">
<li><a href="#generating-an-asset-version-id">Generating an Asset Version ID</a></li>
<li><a href="#using-the-asset-version-id">Using the Asset Version ID</a></li>
</ul>
<h2><a id="generating-an-asset-version-id" href="#generating-an-asset-version-id" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Generating an Asset Version ID</h2>
<pre data-lang="php" class="notranslate"><span class="hl-keyword">&lt;?php</span>

<span class="hl-keyword">return</span> [
    <span class="hl-value">'version'</span> =&gt; <span class="hl-property">env</span>(<span class="hl-value">'ASSETS_VERSION'</span>, <span class="hl-keyword">null</span>),
];
</pre>
<p>Notice that we are referencing a new<code>ASSETS_VERSION</code> environment variable. Add this key to your <code>.env</code> file. We will set up an artisan command to update the value of the <code>ASSETS_VERSION</code> variable for us when needed. We can crib the functionality for this tool from the <code>key:generate</code> command, which performs a very similar task.</p>
<pre data-lang="php" class="notranslate"><span class="hl-keyword">&lt;?php</span>

<span class="hl-keyword">namespace</span> <span class="hl-type">App\Console\Commands</span>;

<span class="hl-keyword">use</span> <span class="hl-type">App\Utilities\Str</span>;
<span class="hl-keyword">use</span> <span class="hl-type">Illuminate\Console\Command</span>;
<span class="hl-keyword">use</span> <span class="hl-type">Illuminate\Console\ConfirmableTrait</span>;

<span class="hl-keyword">class</span> <span class="hl-type">AssetVersioningCommand</span> <span class="hl-keyword">extends</span> <span class="hl-type">Command</span>
{
    <span class="hl-keyword">use</span> <span class="hl-type">ConfirmableTrait</span>;

    <span class="hl-comment">/**
     * The name and signature of the console command.
     *
     * <span class="hl-value">@var</span> string
     */</span>
    <span class="hl-keyword">protected</span> <span class="hl-property">$signature</span> = <span class="hl-value">'assets:version {--force : Force the operation to run when in production}'</span>;

    <span class="hl-comment">/**
     * The console command description.
     *
     * <span class="hl-value">@var</span> string
     */</span>
    <span class="hl-keyword">protected</span> <span class="hl-property">$description</span> = <span class="hl-value">'Generate an asset version identifier'</span>;

    <span class="hl-comment">/**
     * Execute the console command.
     *
     * <span class="hl-value">@return</span> <span class="hl-type">int</span>
     */</span>
    <span class="hl-keyword">public</span> <span class="hl-keyword">function</span> <span class="hl-property">handle</span>()
    {
        <span class="hl-variable">$key</span> = <span class="hl-variable">$this</span>-&gt;<span class="hl-property">generateRandomKey</span>();

        <span class="hl-keyword">if</span> (! <span class="hl-variable">$this</span>-&gt;<span class="hl-property">setKeyInEnvironmentFile</span>(<span class="hl-variable">$key</span>)) {
            <span class="hl-keyword">return</span>;
        }

        <span class="hl-variable">$this</span>-&gt;<span class="hl-property">info</span>(<span class="hl-value">'Asset version key set successfully.'</span>);
    }

    <span class="hl-comment">// ...</span>
}
</pre>
<p>The <code>generateRandomKey()</code> method will be very simple:</p>
<pre data-lang="php" class="notranslate"><span class="hl-keyword">protected</span> <span class="hl-keyword">function</span> <span class="hl-property">generateRandomKey</span>(): <span class="hl-type">string</span>
{
    <span class="hl-keyword">return</span> <span class="hl-type">Str</span>::<span class="hl-property">random</span>(16);
}
</pre>
<p>The <code>setKeyInEnvironmentFile()</code> method is borrowed directly from the <code>key:generate</code> command with some slight modification:</p>
<pre data-lang="php" class="notranslate"><span class="hl-keyword">protected</span> <span class="hl-keyword">function</span> <span class="hl-property">setKeyInEnvironmentFile</span>(<span class="hl-injection">$key</span>)
{
    <span class="hl-variable">$currentKey</span> = <span class="hl-variable">$this</span>-&gt;<span class="hl-property">laravel</span>[<span class="hl-value">'config'</span>][<span class="hl-value">'assets.version'</span>];

    <span class="hl-keyword">if</span> (<span class="hl-property">strlen</span>(<span class="hl-variable">$currentKey</span>) !== 0 <span class="hl-operator">&amp;&amp;</span> (!<span class="hl-variable">$this</span>-&gt;<span class="hl-property">confirmToProceed</span>())) {
        <span class="hl-keyword">return</span> <span class="hl-keyword">false</span>;
    }

    <span class="hl-variable">$this</span>-&gt;<span class="hl-property">writeNewEnvironmentFileWith</span>(<span class="hl-variable">$key</span>);

    <span class="hl-keyword">return</span> <span class="hl-keyword">true</span>;
}
</pre>
<p>The <code>writeNewEnvironmentFileWith()</code> method is also borrowed directly from the <code>key:generate</code> command:</p>
<pre data-lang="php" class="notranslate"><span class="hl-keyword">protected</span> <span class="hl-keyword">function</span> <span class="hl-property">writeNewEnvironmentFileWith</span>(<span class="hl-injection">$key</span>)
{
    <span class="hl-property">file_put_contents</span>(<span class="hl-variable">$this</span>-&gt;<span class="hl-property">laravel</span>-&gt;<span class="hl-property">environmentFilePath</span>(), <span class="hl-property">preg_replace</span>(
        <span class="hl-variable">$this</span>-&gt;<span class="hl-property">keyReplacementPattern</span>(),
        <span class="hl-value">'ASSETS_VERSION='</span> . <span class="hl-variable">$key</span>,
        <span class="hl-property">file_get_contents</span>(<span class="hl-variable">$this</span>-&gt;<span class="hl-property">laravel</span>-&gt;<span class="hl-property">environmentFilePath</span>())
    ));
}
</pre>
<p>Finally, this is the <code>keyReplacementPattern()</code> method, again borrowed from the <code>key:generate</code> command:</p>
<pre data-lang="php" class="notranslate"><span class="hl-keyword">protected</span> <span class="hl-keyword">function</span> <span class="hl-property">keyReplacementPattern</span>()
{
    <span class="hl-variable">$escaped</span> = <span class="hl-property">preg_quote</span>(<span class="hl-value">'='</span> . <span class="hl-variable">$this</span>-&gt;<span class="hl-property">laravel</span>[<span class="hl-value">'config'</span>][<span class="hl-value">'assets.version'</span>], <span class="hl-value">'/'</span>);

    <span class="hl-keyword">return</span> <span class="hl-value">&quot;/^ASSETS_VERSION{$escaped}/m&quot;</span>;
}
</pre>
<p><a href="https://stagerightlabs.com/snippets/SNR8FWB7">You can see the complete file here.</a> With this command in place, we can generate a new asset version identifier upon each new deployment by adding a call to the <code>assets:version</code> command to our deployment script.</p>
<h2><a id="using-the-asset-version-id" href="#using-the-asset-version-id" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Using the Asset Version ID</h2>
<p>Now that we have the asset version ID available to us, we need to update our asset urls to include the ID as a query parameter. We can do that with a custom blade directive. Add this to the <code>boot()</code> method of your <code>AppServiceProvider</code>:</p>
<pre data-lang="php" class="notranslate"><span class="hl-type">Blade</span>::<span class="hl-property">directive</span>(<span class="hl-value">'version'</span>, <span class="hl-keyword">function</span>(<span class="hl-injection">$path</span>) {
    <span class="hl-keyword">return</span> <span class="hl-value">&quot;&lt;?php echo config('assets.version') ? asset({$path}) . '?v=' . config('assets.version') : asset({$path}); ?&gt;&quot;</span>;
});
</pre>
<p>This blade directive accepts a partial path to an asset. It uses the <code>asset()</code> url helper to generate a full URL to the asset, then appends our version ID to the url as a query string. If no version is found the query parameter will be omitted.</p>
<p>We will now need to update our layout files to use this directive when loading assets:</p>
<pre data-lang="html" class="notranslate">&lt;<span class="hl-keyword">script</span> <span class="hl-property">src</span>=&quot;@version('/js/app.js')&quot;&gt;&lt;/<span class="hl-keyword">script</span>&gt;
</pre>
<p>We can now reference versioned assets anywhere we need to in our application, and we can ensure that browsers will always pull in the latest version of our assets when we deploy updates.</p>
]]>
    </content>
    <link rel="alternate" href="https://stagerightlabs.com/blog/asset-versioning-in-laravel" />
  </entry>
    <entry>
    <title>
      <![CDATA[You Might Not Need Laravel Mix]]>
    </title>
    <id>tag:stagerightlabs.com,2021-03-21T00:00:00+0000:1616284800</id>
    <updated>2021-03-21T00:00:00+00:00</updated>
    <summary>
      <![CDATA[Let's explore an alternate strategy for compiling front-end assets that is particularly well suited to working with TALL stack applications.]]>
    </summary>
    <content type="html">
      <![CDATA[<p><a href="https://laravel-mix.com/">Laravel Mix</a> is incredibly helpful. As far as I am aware it is the easiest way to get up and running with webpack when you are working on a backend application. However, there are certain situations where even Laravel Mix might be more than you need. This is particularly true when working with a <a href="https://tallstack.dev/">TALL stack</a> application where most of your styling will be generated by Tailwind CSS and most of your Javascript will be managed by Alpine or Livewire.</p>
<p>Let's take a look at an alternative asset pipeline configuration that has much less overhead and works particularly well in the TALL stack context.</p>
<p><a href="https://stagerightlabs.com/snippets/SN5RNSZX">TLDR? See the final <code>package.json</code> definition here.</a></p>
<ul class="table-of-contents">
<li><a href="#javascript">Javascript</a></li>
<li><a href="#styles">Styles</a></li>
<li><a href="#watching-files">Watching Files</a></li>
<li><a href="#our-new-packagejson-file">Our new Package.json file</a></li>
<li><a href="#asset-versioning">Asset Versioning</a></li>
</ul>
<h2><a id="javascript" href="#javascript" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Javascript</h2>
<p><a href="https://esbuild.github.io/">esbuild</a> is a javascript bundler written in golang. It has a very small footprint, and it compiles javascript very quickly. It can be installed with NPM:</p>
<pre data-lang="txt" class="notranslate">npm install esbuild --save-dev
</pre>
<p>To compile javascript we pass it our main javascript file using flags to indicate the type of output we want to create. For example, to build our javascript for local development we might do something like this:</p>
<pre data-lang="txt" class="notranslate">./node_modules/.bin/esbuild resources/js/app.js --outfile=public/js/app.js --target=es6 --bundle --sourcemap
</pre>
<p>A production build might look something like this:</p>
<pre data-lang="txt" class="notranslate">./node_modules/.bin/esbuild resources/js/app.js --outfile=public/js/app.js --target=es6 --bundle --minify --define:process.env.NODE_ENV=\\\&quot;production\\\&quot;
</pre>
<p>The first argument is our javascript entry point; the file that serves as the orchestrator of our javascript bundle. In that file you will import any third party packages you are using, as well as any custom javascript you have written for your application. In most Laravel applications this is the <code>resources/js/app.js</code> file, but it may be different in your project.</p>
<p>The <code>--outfile</code> argument tells esbuild where you want the compiled javascript to be written. In this case we are sending it to <code>public/js/app.js</code>. As a side note, I recommend adding automatically generated files like this to <code>.gitignore</code> so that they are not tracked in your repository. This will will reduce commit noise over the long run, though it does mean that you will need to run the asset pipeline on each deployment - this is something you will likely be doing anyway.</p>
<p>The <code>--target</code> argument tells esbuild what format of javascript you want to compile to. This can be either a language version such as &quot;es6&quot; or &quot;es2020&quot;, or a list of browser engines: &quot;chrome&quot;, &quot;firefox&quot;, &quot;safari&quot;, etc. The default value is &quot;esnext&quot;, which is very cutting edge. At the moment I am using the &quot;es6&quot; target for most of my projects, but that will likely change in the future.</p>
<p>The <code>--bundle</code> flag tells esbuild to bundle all of the javascript together, rather than linking out to separate files in the <code>node_modules</code> folder. I consider this to be optional for local development, but it is a requirement for production builds; without it your javascript will break in production, or behave unexpectedly at the very least.</p>
<p>The <code>--sourcemap</code> flag will trigger the creation of a source map file which can be very helpful when doing local development. The <code>minify</code> flag triggers automatic code minimization, as you can imagine.</p>
<p>The <code>--define</code> argument has many uses; here we are telling esbuild to operate with the <code>NODE_ENV=production</code> environment variable in place. Note the extra escape slashes - these are required to ensure that the value is parsed correctly by the binary.</p>
<h2><a id="styles" href="#styles" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Styles</h2>
<p><a href="https://postcss.org/">PostCSS</a> is &quot;a tool for transforming CSS with javascript&quot;. It is incredibly versatile, and it is the engine that powers TailwindCSS. You will find that PostCSS is the best way to start working with next generation CSS code in your projects today. Most of the features you might find useful in SASS or LESS can be replicated with PostCSS fairly easily; it is possible that you could remove those tools entirely from your project and just use PostCSS instead.</p>
<p>We will use the PostCSS-CLI tool to run our css files through postcss and generate our compiled styles file. We can install both PostCSS and the CLI tool like so:</p>
<pre data-lang="txt" class="notranslate">npm install postcss postcss-cli --save-dev
</pre>
<p>Before we can run the CLI build tool we have to define a configuration file that will tell PostCSS how to operate.</p>
<pre data-lang="js" class="notranslate">module.<span class="hl-property">exports</span> = {
    <span class="hl-property">plugins</span>: {
        <span class="hl-property">tailwindcss</span>: {},
        <span class="hl-property">autoprefixer</span>: {},
    },
};
</pre>
<p>Here we are registering two plugins: Tailwind and Autoprefixer. These will need to be installed via NPM before you can use them in your asset pipeline. There are <a href="https://www.postcss.parts/">many plugins</a> available in the PostCSS ecosystem; the possibilities are endless.</p>
<p>To create a css file for local development we can run this command:</p>
<pre data-lang="txt" class="notranslate">./node_modules/.bin/postcss resources/css/app.css --output public/css/app.css --map --verbose
</pre>
<p>As with esbuild, the first argument we pass to the binary is the file we want to have processed. This is the entry point into our CSS. You could also point it to a directory if you want to combine multiple files together.</p>
<p>The <code>--output</code> argument names the destination for our compiled CSS. The <code>--map</code> flag tells PostCSS to generate a source map. The <code>--verbose</code> option tells the CLI to print contextual information to the terminal; without it the command output is very minimal.</p>
<p>To compress our styles in production we will use cssnano, which is a PostCSS plugin for minimizing CSS. We will only want to run minimization for production builds; to do that we will need to modify our <code>postcss.config.js</code> file to provide it with some context:</p>
<pre data-lang="js" class="notranslate">module.<span class="hl-property">exports</span> = (ctx) =&gt; ({
    <span class="hl-property">plugins</span>: {
        <span class="hl-property">tailwindcss</span>: {},
        <span class="hl-property">autoprefixer</span>: {},
        <span class="hl-property">cssnano</span>: ctx.<span class="hl-property">env</span> === <span class="hl-value">&quot;production&quot;</span> ? {} : <span class="hl-keyword">false</span>,
    },
});
</pre>
<p>This tells PostCSS to only use the cssnano plugin when the <code>NODE_ENV</code> environment variable is set to 'production'. To generate our production build we can modify our build command like so:</p>
<pre data-lang="txt" class="notranslate">NODE_ENV=production ./node_modules/.bin/postcss resources/css/app.css --output public/css/app.css --verbose
</pre>
<p>The CLI tool has <a href="https://github.com/postcss/postcss-cli#usage">many more options</a> that are worth investigating.</p>
<h2><a id="watching-files" href="#watching-files" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Watching Files</h2>
<p>Our local development experience can improve quite a bit if we can have our asset pipeline monitor our resource files and re-compile them automatically when they are changed. Fortunately, both esbuild and the postcss-cli provide options for watching files and compiling them automatically for us.</p>
<p>For esbuild we can add a <code>--watch</code> flag to monitor our javascript files:</p>
<pre data-lang="txt" class="notranslate">./node_modules/.bin/esbuild resources/js/app.js --outfile=public/js/app.js --target=es6 --bundle --sourcemap --watch
</pre>
<p>The PostCSS-CLI tool has the same option:</p>
<pre data-lang="txt" class="notranslate">./node_modules/.bin/postcss resources/css/app.css --output public/css/app.css --map --verbose --watch
</pre>
<p>If we define a separate NPM script for each of these commands we can then run them both at the same time:</p>
<pre data-lang="txt" class="notranslate">npm run watch:js &amp; npm run watch:css
</pre>
<p>With that in place we should have everything we need to work on our application locally and then deploy it to production.</p>
<h2><a id="our-new-packagejson-file" href="#our-new-packagejson-file" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Our new Package.json file</h2>
<p>Here is a <code>package.json</code> file that includes all of the dependencies we have discussed and the scripts we have defined:</p>
<pre data-lang="json" class="notranslate"><span class="hl-property">{</span>
    <span class="hl-keyword">&quot;private&quot;</span>: true,
    <span class="hl-keyword">&quot;scripts&quot;</span>: <span class="hl-property">{</span>
        <span class="hl-value">&quot;build:css&quot;</span>: <span class="hl-value">&quot;NODE_ENV=production postcss resources/css/app.css --output public/css/app.css --verbose&quot;</span>,
        <span class="hl-value">&quot;build:js&quot;</span>: <span class="hl-value">&quot;esbuild resources/js/app.js --outfile=public/js/app.js --target=es6 --bundle --minify --define:process.env.NODE_ENV=\\\&quot;</span>production\\\<span class="hl-value">&quot;&quot;</span>,
        <span class="hl-keyword">&quot;build&quot;</span>: <span class="hl-value">&quot;npm run build:js &amp;&amp; npm run build:css&quot;</span>,
        <span class="hl-value">&quot;local:css&quot;</span>: <span class="hl-value">&quot;postcss resources/css/app.css --output public/css/app.css --map --verbose&quot;</span>,
        <span class="hl-value">&quot;local:js&quot;</span>: <span class="hl-value">&quot;esbuild resources/js/app.js --outfile=public/js/app.js --target=es6 --bundle --sourcemap&quot;</span>,
        <span class="hl-keyword">&quot;local&quot;</span>: <span class="hl-value">&quot;npm run local:js &amp;&amp; npm run local:css&quot;</span>,
        <span class="hl-value">&quot;watch:css&quot;</span>: <span class="hl-value">&quot;postcss resources/css/app.css --output public/css/app.css --map --verbose --watch&quot;</span>,
        <span class="hl-value">&quot;watch:js&quot;</span>: <span class="hl-value">&quot;esbuild resources/js/app.js --outfile=public/js/app.js --target=es6 --bundle --sourcemap --watch&quot;</span>,
        <span class="hl-keyword">&quot;watch&quot;</span>: <span class="hl-value">&quot;npm run watch:js &amp; npm run watch:css&quot;</span>
    <span class="hl-property">}</span>,
    <span class="hl-keyword">&quot;dependencies&quot;</span>: <span class="hl-property">{</span>
        <span class="hl-keyword">&quot;alpinejs&quot;</span>: <span class="hl-value">&quot;^2.8.1&quot;</span>
    <span class="hl-property">}</span>,
    <span class="hl-keyword">&quot;devDependencies&quot;</span>: <span class="hl-property">{</span>
        <span class="hl-keyword">&quot;autoprefixer&quot;</span>: <span class="hl-value">&quot;^10.2.5&quot;</span>,
        <span class="hl-keyword">&quot;esbuild&quot;</span>: <span class="hl-value">&quot;^0.9.4&quot;</span>,
        <span class="hl-keyword">&quot;postcss&quot;</span>: <span class="hl-value">&quot;^8.2.8&quot;</span>,
        <span class="hl-keyword">&quot;postcss-cli&quot;</span>: <span class="hl-value">&quot;^8.3.1&quot;</span>,
        <span class="hl-keyword">&quot;tailwindcss&quot;</span>: <span class="hl-value">&quot;^2.0.4&quot;</span>
    <span class="hl-property">}</span>
<span class="hl-property">}</span>
</pre>
<p>Notes:</p>
<ul>
<li>I recommend that you add all of your generated assets to the <code>.gitignore</code> file and then rebuild them as part of your deployment process.</li>
<li>In the <code>build</code> and <code>local</code> scripts above we separate our commands with two ampersands; this means that if the first command fails the second one will not run.</li>
<li>In the <code>watch</code> script above we separate our commands with one ampersand; this means they will be run simultaneously.</li>
<li>When you remove Laravel Mix from your project, you can no longer use the <code>mix()</code> helper in your template files.</li>
<li>I have not tried running these commands on Windows - your mileage may vary.</li>
</ul>
<h2><a id="asset-versioning" href="#asset-versioning" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Asset Versioning</h2>
<p>The final step in setting up our asset pipeline will be implementing asset versioning for browser cache busting. This, however, will be <a href="https://stagerightlabs.com/blog/asset-versioning-in-laravel">a topic for a separate post</a>.</p>
]]>
    </content>
    <link rel="alternate" href="https://stagerightlabs.com/blog/you-might-not-need-laravel-mix" />
  </entry>
    <entry>
    <title>
      <![CDATA[Automatic Code Formatting With Git Hooks]]>
    </title>
    <id>tag:stagerightlabs.com,2021-03-05T00:00:00+0000:1614902400</id>
    <updated>2021-03-05T00:00:00+00:00</updated>
    <summary>
      <![CDATA[Git hooks are a powerful tool that can be leveraged for many uses. Let's examine how we can use the 'pre-commit' hook to run code formatting tools automatically.]]>
    </summary>
    <content type="html">
      <![CDATA[<p>Automatic code formatting can be very helpful. Keeping your code consistent with a standard layout makes it much easier for new developers to step into your project and understand what is going on. If you are like me, however, remembering to run the formatter on a periodic basis can be problematic. You may also end up with extra commits in your SCM tool that are just for formatting; which can be distracting.</p>
<p>There are two primary options available to us: 1) We can configure our code editor to format code automatically, or 2) We can use a git &quot;pre-commit&quot; hook to run a formatting script for us automatically. In this post I will be discussing the later.</p>
<p><a href="https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks">Git hooks</a> are configurable opportunities to run custom commands when performing common tasks with git. Within the <code>.git</code> folder in your project there is a folder called &quot;hooks&quot;. This folder will store our bash scripts that we want git to trigger for us. If you take a look in that folder now you will see a handful of example files.</p>
<p>Give your script the name of a lifecycle hook and that script will be run when the hook is called. There are several <a href="https://githooks.com/">lifecycle hooks</a> available, each serving a slightly different purpose. The &quot;pre-commit&quot; hook is the best candidate for us; it is run just before a commit is recorded. We can use that hook to trigger our code formatter and the changes will be included in the commit record. Let's set that up now.</p>
<p>The first thing to think about is where you want to keep your script. You have the option of keeping it directly in the <code>.git/hooks</code> folder, but it won't be tracked as part of the rest of your repository. I prefer to keep the file somewhere in the regular part of the repo and then use a symbolic link to add it to the hooks folder. This way the script is under version control and new developers can use it themselves in the future if they so desire.</p>
<p>Create a file called <code>pre-commit.sh</code> and store it somewhere convenient. Then set up a symbolic link:</p>
<pre data-lang="txt" class="notranslate">$ ln -s ../../pre-commit.sh .git/hooks/pre-commit
</pre>
<p>You will also need to make sure the file is executable:</p>
<pre data-lang="txt" class="notranslate">$ chmod +x pre-commit.sh
</pre>
<p>Now we need to decide what we want this script to do.</p>
<p>For the sake of this demonstration let's assume you are working on a PHP project and you want to use the <a href="https://github.com/FriendsOfPhp/PHP-CS-Fixer">php-cs-fixer package</a> to perform automatic formatting on the php files in your repository. A very minimal version of this script could look something like this:</p>
<pre data-lang="txt" class="notranslate">#!/usr/bin/env bash

vendor/bin/php-cs-fixer fix
</pre>
<p>This will read your <code>.php_cs</code> configuration file and apply those rules to all of the php files in your codebase before every commit. This is essentially the same as calling the tool directly from the command line - the usage is exactly the same.</p>
<p>I am currently working on a project using a version of php that I don't have installed on my development machine. We can use docker to provide the same functionality without having to install multiple versions of PHP on the host machine. I have created a set of <a href="https://hub.docker.com/r/stagerightlabs/php-test-runner/tags">generic PHP docker images</a> that is ideal for this purpose. Here is a version of that same formatting script that uses docker instead of the locally installed PHP instance:</p>
<pre data-lang="txt" class="notranslate">#!/usr/bin/env bash

docker run --rm \
    -u 1000 \
    -v $(pwd):/var/www \
    -w /var/www \
    stagerightlabs/php-test-runner:7.4 /bin/bash -c &quot;vendor/bin/php-cs-fixer fix --quiet&quot;
</pre>
<p>Most of the usage here is specific to these particular docker images; your situation may be different. The <code>-v $(pwd):/var/www</code> argument mounts the current directory into the docker image at <code>/var/www</code>. <code>-w /var/www</code> sets the active working directory. We then call php-cs-fixer via the container, using the &quot;quiet&quot; flag to hide the output messages.</p>
<p>I find that this works very well; however the formatter is still looking at all the php files in the repo, which can be time consuming even with caching in place. This technique, from <a href="https://gist.github.com/fesor/1043aec3f1aeac7d801c270e0fba36cd">Sergey Protko</a>, will limit the formatter to only the files that are going to be committed:</p>
<pre data-lang="txt" class="notranslate">#!/usr/bin/env bash

CHANGED_FILES=$(git diff --cached --name-only --diff-filter=ACM -- '*.php')

if [ -n &quot;$CHANGED_FILES&quot; ]; then
    vendor/bin/php-cs-fixer fix $CHANGED_FILES;
    git add $CHANGED_FILES;
fi
</pre>
<p>With a script like this in place you will never have to worry about keeping up with formatting your codebase manually, or adding extra commits just for formatting changes. Take a look at the other git hooks that are available as well - they can be a very powerful tool and a great addition to your tool belt.</p>
]]>
    </content>
    <link rel="alternate" href="https://stagerightlabs.com/blog/automatic-code-formatting-with-git-hooks" />
  </entry>
    <entry>
    <title>
      <![CDATA[Host Elixir Apps on Forge Servers]]>
    </title>
    <id>tag:stagerightlabs.com,2020-12-18T00:00:00+0000:1608249600</id>
    <updated>2020-12-18T00:00:00+00:00</updated>
    <summary>
      <![CDATA[Servers provisioned by Laravel Forge can be used for almost anything. Let's take a look at hosting an Elixir application on a server managed by Forge.]]>
    </summary>
    <content type="html">
      <![CDATA[<p>Laravel <a href="https://forge.laravel.com">Forge</a> is a server provisioning tool that is typically used to set up servers for hosting PHP applications. However, the basic setup it provides is a great jumping-off point. It can be used for hosting a variety of different types of applications.</p>
<p>Let's take a look at hosting an <a href="https://elixir-lang.org/">Elixir</a> application on a server provisioned by Forge.</p>
<p>TLDR: <a href="https://gist.github.com/rydurham/41904723ab07d8d60fa8295ee6f64822">https://gist.github.com/rydurham/41904723ab07d8d60fa8295ee6f64822</a></p>
<ul class="table-of-contents">
<li><a href="#install-elixir">Install Elixir</a></li>
<li><a href="#creating-the-site">Creating the Site</a></li>
<li><a href="#releases">Releases</a></li>
<li><a href="#nginx-configuration">Nginx Configuration</a></li>
<li><a href="#the-deployment-script">The Deployment Script</a></li>
<li><a href="#conclusion">Conclusion</a></li>
<li><a href="#nb">NB</a></li>
</ul>
<h2><a id="install-elixir" href="#install-elixir" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Install Elixir</h2>
<p>Once Forge has created a new server for us, we will first need to install Elixir and Erlang. Connect to the server via SSH and then run the Elixir <a href="https://elixir-lang.org/install.html">installation steps</a>:</p>
<pre data-lang="txt" class="notranslate">~$ wget https://packages.erlang-solutions.com/erlang-solutions_2.0_all.deb &amp;&amp; sudo dpkg -i erlang-solutions_2.0_all.deb
~$ sudo apt update
~$ sudo apt install esl-erlang
~$ sudo apt install elixir
~$ rm erlang-solutions_2.0_all.deb
</pre>
<p>You could also set this task up as a <a href="https://mattstauffer.com/blog/laravel-forge-using-recipes/">recipe</a> if you want to run it again on new servers down the road.</p>
<p>We can verify the installation by running:</p>
<pre data-lang="txt" class="notranslate">~$ elixir -v
Erlang/OTP 23 [erts-11.1.4] [source] [64-bit] [smp:1:1] [ds:1:1:10] [async-threads:1] [hipe]

Elixir 1.11.2 (compiled with Erlang/OTP 23)
</pre>
<h2><a id="creating-the-site" href="#creating-the-site" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Creating the Site</h2>
<p>We can now create the site in our Forge management panel just like any other site. Go to the overview page for your new server and use the &quot;Add site&quot; tool to set up your new site. Select &quot;Static HTML&quot; as your project type, and the project root (&quot;/&quot;) as your web directory. Once the site has been set up don't run a deployment just yet; we will first need to modify the nginx configuration and the deployment script to work with Elixir <a href="https://elixir-lang.org/getting-started/mix-otp/config-and-releases.html#releases">releases</a>.</p>
<h2><a id="releases" href="#releases" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Releases</h2>
<p>As noted in the Elixir documentation:</p>
<blockquote>
<p>A release is a self-contained directory that consists of your application code, all of its dependencies, plus the whole Erlang Virtual Machine (VM) and runtime.</p>
</blockquote>
<p>When we create a release it contains everything needed to run our application in a single directory with a corresponding binary. This binary can then be run as a daemon process listening for requests on a system port. The only catch is that you have to build the binary on the same type of system that you will be hosting it on. In our case, we will use a forge deployment script to build our release and start it as a daemon process every time we want to update the code.</p>
<p>Configuring an Elixir application for release is outside the scope of this post, but the Elixir documentation covers the topic <a href="https://elixir-lang.org/getting-started/mix-otp/config-and-releases.html">very well</a>. If you are working with Phoenix there is also <a href="https://hexdocs.pm/phoenix/releases.html">excellent information</a> about releases in that documentation as well.</p>
<h2><a id="nginx-configuration" href="#nginx-configuration" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Nginx Configuration</h2>
<p>The default nginx site configuration provided by Forge is very comprehensive; we only need to make a few small modifications to get things working the way we want. We will be using a reverse proxy to get nginx to forward web traffic to our application daemon.</p>
<p>First we will add the reverse proxy. Put this above the <code>server</code> block, near the top of the file:</p>
<pre data-lang="txt" class="notranslate">upstream site {
 server localhost:4000
}
</pre>
<p>&quot;site&quot; is a shorthand name for the service we are setting up. You should use something more specific to your application. Also, I am using port 4000 here, but you can configure your Elixir release to use any port you would like.</p>
<p>Now we can update the <code>server</code> block itself. As of this writing, there are two <code>location</code> blocks in the default nginx configuration. One is for handling the site root at <code>/</code> and the other is specifically for handling php files. Remove the second block (<code>location ~ \.php$</code>) completely; we won't be needing it.</p>
<p>Update the contents of the <code>location /</code> block like so:</p>
<pre data-lang="txt" class="notranslate">location / {
    proxy_http_version 1.1; # Required for phoenix channel websocket negotiation
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://site;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection &quot;upgrade&quot;;
}
</pre>
<p>Here we are configuring our proxy and then using the <code>proxy_pass http://site</code> line to forward requests to our upstream server on port 4000. Replace &quot;site&quot; with whatever name you used for your upstream service.</p>
<p>As of the time of this writing we need to enforce the use of HTTP1.1 to allow websocket negotiations to work in the way that Elixir and Phoenix expect them to. Most of the proxy configuration listed here is used for that purpose.</p>
<p>With those changes in place you can save the script and restart nginx. Now, on to the deployment script.</p>
<h2><a id="the-deployment-script" href="#the-deployment-script" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>The Deployment Script</h2>
<p>A deployment script outlines the actions that Forge will perform whenever you request a site deployment. The default deployment script generated for new sites is geared towards PHP applications. Delete everything that is there and replace it with this:</p>
<pre data-lang="txt" class="notranslate">cd /home/forge/www.example.com
# Fetch the latest version of the code
git pull origin main

# Ensure we have access to mix
if ! [ -x &quot;$(command -v mix)&quot; ]; then
  echo 'Error: Elixir is not installed.' &gt;&amp;2
  exit 1
fi

if ! [ -d /home/forge/site_logs ]; then
  mkdir -p /home/forge/site_logs
fi

# Ensure we have access to hex and rebar
mix local.hex --force
mix local.rebar --force

# Install dependencies
mix deps.get --only prod
git checkout mix.lock
MIX_ENV=prod mix compile

# Compile assets
npm install --no-save --prefix ./apps/site_web/assets
npm run deploy --prefix ./apps/site_web/assets
MIX_ENV=prod mix phx.digest /home/forge/www.example.com/apps/site_web/priv/static

# Run the migrations
# MIX_ENV=prod mix ecto.migrate

# Generate the release
MIX_ENV=prod mix release production --overwrite

# Stop the existing process if it exists
_build/prod/rel/production/bin/production stop

# Start the release as a daemon process
RELEASE_TMP=/home/forge/rcd_logs _build/prod/rel/production/bin/production daemon

# Log the new OS PID
_build/prod/rel/production/bin/production pid
</pre>
<p>Let's break it down into chunks:</p>
<pre data-lang="txt" class="notranslate">cd /home/forge/www.example.com
git pull origin main
</pre>
<p>First we move into the project's root directory and pull in the latest version of the code with git. Make sure you specify whichever repo branch you are using for deployments here. I am using &quot;main&quot;.</p>
<pre data-lang="txt" class="notranslate">if ! [ -x &quot;$(command -v mix)&quot; ]; then
  echo 'Error: Elixir is not installed.' &gt;&amp;2
  exit 1
fi
</pre>
<p>We won't be able to get very far if we can't use the <code>mix</code> tool provided by Elixir. Here we are checking to make sure it is available. If it isn't then it is likely that something went wrong when we installed Elixir on the server.</p>
<pre data-lang="txt" class="notranslate">if ! [ -d /home/forge/rcd_logs ]; then
  mkdir -p /home/forge/rcd_logs
fi
</pre>
<p>We are going to use a separate directory for storing our application logs. Here we are making sure that the directory exists. If it doesn't we will create it.</p>
<pre data-lang="txt" class="notranslate">mix local.hex --force
mix local.rebar --force
</pre>
<p>We will need both <code>hex</code> and <code>rebar</code> to manage our Elixir dependencies and build our release. Here we are checking to make sure they are available to us.</p>
<pre data-lang="txt" class="notranslate">mix deps.get --only prod
git checkout mix.lock
MIX_ENV=prod mix compile
</pre>
<p>Here we are fetching our production dependencies and compiling them for use in our production environment. The <code>mix.lock</code> file might drift a bit after fetching the dependencies; I am reverting the file to prevent any changed files from stopping a <code>git pull</code> in the future.</p>
<pre data-lang="txt" class="notranslate">npm install --no-save --prefix ./apps/site_web/assets
npm run deploy --prefix ./apps/site_web/assets
MIX_ENV=prod mix phx.digest /home/forge/www.example.com/apps/site_web/priv/static
</pre>
<p>Now we are compiling our front end assets. You will need to update the <code>prefix</code> value to point to your own asset directory. The <code>phx.digest</code> command prepares our static assets for use with our release binary.</p>
<pre data-lang="txt" class="notranslate"># MIX_ENV=prod mix ecto.migrate
</pre>
<p>If you want to automatically run new database migrations you can uncomment this line. I tend to prefer to run migrations manually, but the choice is yours.</p>
<pre data-lang="txt" class="notranslate">MIX_ENV=prod mix release production --overwrite
</pre>
<p>This is where we build our new release binary. The <code>--overwrite</code> flag tells Elixir to replace the currently tagged release rather than creating a new one with a new version number. You may decide that you want to keep your old releases and tag a new build version for each release; this will require that you update your release configuration in the application for each deployment.</p>
<pre data-lang="txt" class="notranslate">_build/prod/rel/production/bin/production stop
</pre>
<p>If we have an existing release running this command will stop it. If there is no existing release this command will error, but that doesn't matter for our purposes.</p>
<pre data-lang="txt" class="notranslate">RELEASE_TMP=/home/forge/rcd_logs _build/prod/rel/production/bin/production daemon
</pre>
<p>Here we start up a new daemon process with the newly built binary. Note that we are setting an environment variable that tells the binary where to put its log files - this is the same folder path we created earlier.</p>
<p>The exact path to the binary will depend on your release configuration.</p>
<pre data-lang="txt" class="notranslate">_build/prod/rel/production/bin/production pid
</pre>
<p>I like to include the newly started process ID in the deployment log; this is optional.</p>
<h2><a id="conclusion" href="#conclusion" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Conclusion</h2>
<p>With this deployment script in place you can now use Forge to automatically build and deploy Elixir application releases on-demand. How neat is that? Forge is a remarkable tool.</p>
<h2><a id="nb" href="#nb" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>NB</h2>
<p>There are a couple things to keep in mind:</p>
<ul>
<li>If you restart the server your application process will not automatically restart; you will have to connect via SSH and start the process manually.</li>
<li>This deployment script is not perfect. Occasionally it will build the release but not successfully start the daemon process. When that happens I start the process by connecting to the server via SSH and running the commands manually.</li>
<li>I have <a href="https://gist.github.com/rydurham/41904723ab07d8d60fa8295ee6f64822">set up a gist</a> for this deployment script. Feel free to leave a comment if you have any ideas for improvement.</li>
</ul>
]]>
    </content>
    <link rel="alternate" href="https://stagerightlabs.com/blog/host-elixir-apps-on-forge-servers" />
  </entry>
    <entry>
    <title>
      <![CDATA[Vue and Threejs - Part Two]]>
    </title>
    <id>tag:stagerightlabs.com,2019-04-13T00:00:00+0000:1555113600</id>
    <updated>2019-04-13T00:00:00+00:00</updated>
    <summary>
      <![CDATA[Let's continue our experiment with Three.js and Vue.js. We will look at setting up a control panel that lets users manually adjust the content of our three dimensional scene.]]>
    </summary>
    <content type="html">
      <![CDATA[<p>Now that we have our three-dimensional screen rendering, let's see if we can add some controls that will allow the user to manipulate what they see.</p>
<p>Let's start by displaying the coordinates of the camera position within the scene. Create a new <code>ControlPanel.vue</code> component in your <code>src/components/</code> directory.</p>
<p>We will use a Vuex getter to retrieve the camera position and display it on the control panel:</p>
<pre data-lang="js" class="notranslate"><span class="hl-property">getters</span>: {
  <span class="hl-property">CAMERA_POSITION</span>: state =&gt; {
    <span class="hl-keyword">return</span> state.<span class="hl-property">camera</span> ? state.<span class="hl-property">camera</span>.<span class="hl-property">position</span> : <span class="hl-keyword">null</span>;
  }
},
</pre>
<p>Let's import this getter into our Control Panel component:</p>
<pre data-lang="js" class="notranslate"><span class="hl-keyword">import</span> { mapGetters, mapMutations } <span class="hl-keyword">from</span> <span class="hl-value">&quot;vuex&quot;</span>;
<span class="hl-keyword">export</span> <span class="hl-keyword">default</span> {
    <span class="hl-property">data</span>() {
        <span class="hl-keyword">return</span> {
            <span class="hl-property">axisLinesVisible</span>: <span class="hl-keyword">true</span>,
            <span class="hl-property">pyramidsVisible</span>: <span class="hl-keyword">true</span>,
        };
    },
    <span class="hl-property">computed</span>: {
        ...<span class="hl-property">mapGetters</span>([<span class="hl-value">&quot;CAMERA_POSITION&quot;</span>]),
    },
    <span class="hl-comment">// ...</span>
};
</pre>
<p>You can see that we have also added two boolean flags to the component's data object. Later on we will use these to toggle the visibility of the pyramids and axis lines in our scene.</p>
<p>By mapping our vuex <code>CAMERA_POSITION</code> into the Control Panel's computed data object, we can display those coordinates and they will update in real time:</p>
<pre data-lang="html" class="notranslate">&lt;<span class="hl-keyword">div</span> <span class="hl-property">v-if</span>=&quot;CAMERA_POSITION&quot; <span class="hl-property">class</span>=&quot;border-grey-darkest mb-2 border-b pb-2&quot;&gt;
    &lt;<span class="hl-keyword">p</span> <span class="hl-property">class</span>=&quot;text-grey-light mb-1 font-bold&quot;&gt;Camera Position&lt;/<span class="hl-keyword">p</span>&gt;
    &lt;<span class="hl-keyword">p</span> <span class="hl-property">class</span>=&quot;text-grey-light mb-2 flex w-full justify-between&quot;&gt;
        X:&lt;<span class="hl-keyword">span</span> <span class="hl-property">class</span>=&quot;text-white&quot;&gt;{{ CAMERA_POSITION.x }}&lt;/<span class="hl-keyword">span</span>&gt;
    &lt;/<span class="hl-keyword">p</span>&gt;
    &lt;<span class="hl-keyword">p</span> <span class="hl-property">class</span>=&quot;text-grey-light mb-2 flex w-full justify-between&quot;&gt;
        Y:&lt;<span class="hl-keyword">span</span> <span class="hl-property">class</span>=&quot;text-white&quot;&gt;{{ CAMERA_POSITION.y }}&lt;/<span class="hl-keyword">span</span>&gt;
    &lt;/<span class="hl-keyword">p</span>&gt;
    &lt;<span class="hl-keyword">p</span> <span class="hl-property">class</span>=&quot;text-grey-light mb-2 flex w-full justify-between&quot;&gt;
        Z:&lt;<span class="hl-keyword">span</span> <span class="hl-property">class</span>=&quot;text-white&quot;&gt;{{ CAMERA_POSITION.z }}&lt;/<span class="hl-keyword">span</span>&gt;
    &lt;/<span class="hl-keyword">p</span>&gt;
    <span class="hl-comment">&lt;!-- more... --&gt;</span>
&lt;/<span class="hl-keyword">div</span>&gt;
</pre>
<p>(Check out the <a href="https://github.com/stagerightlabs/Vue-Three-Demo/blob/master/src/components/ControlPanel.vue">project repo</a> to see how this component has been styled with Tailwind utility classes.)</p>
<p>I have found that the trackball control implementation in Three.js can be counter-intuitive at times. It is very easy for the user to end up somewhere they did not intend to go. Let's add a button to our control panel that will reset the camera position to origin. We will do that with (you guessed it) a Vuex mutation:</p>
<pre data-lang="js" class="notranslate"><span class="hl-property">mutations</span>: {
  <span class="hl-comment">// ...</span>
  <span class="hl-property">SET_CAMERA_POSITION</span>(state, { x, y, z }) {
    <span class="hl-keyword">if</span> (state.<span class="hl-property">camera</span>) {
      state.<span class="hl-property">camera</span>.<span class="hl-property">position</span>.<span class="hl-property">set</span>(x, y, z);
    }
  },
  <span class="hl-property">RESET_CAMERA_ROTATION</span>(state) {
    <span class="hl-keyword">if</span> (state.<span class="hl-property">camera</span>) {
      state.<span class="hl-property">camera</span>.<span class="hl-property">rotation</span>.<span class="hl-property">set</span>(0, 0, 0);
      state.<span class="hl-property">camera</span>.<span class="hl-property">quaternion</span>.<span class="hl-property">set</span>(0, 0, 0, 1);
      state.<span class="hl-property">camera</span>.<span class="hl-property">up</span>.<span class="hl-property">set</span>(0, 1, 0);
      state.<span class="hl-property">controls</span>.<span class="hl-property">target</span>.<span class="hl-property">set</span>(0, 0, 0);
    }
  },
  <span class="hl-comment">// ...</span>
}
</pre>
<p>Note that resetting the camera position requires more than just changing the camera position. We also have to account for the rotation of the camera around three <a href="https://en.wikipedia.org/wiki/Aircraft_principal_axes#Principal_axes">additional axis</a>. (Check out the Three.js documentation for more details.)</p>
<p>Now that the mutation is in place, let's add it to our Control Panel:</p>
<pre data-lang="html" class="notranslate">&lt;<span class="hl-keyword">p</span> <span class="hl-property">class</span>=&quot;flex items-center&quot;&gt;
    &lt;<span class="hl-keyword">button</span>
        <span class="hl-property">class</span>=&quot;bg-grey-light mx-auto cursor-pointer p-2 shadow-sm&quot;
        @<span class="hl-property">click</span>=&quot;resetCameraPosition&quot;
    &gt;
        Reset Camera
    &lt;/<span class="hl-keyword">button</span>&gt;
&lt;/<span class="hl-keyword">p</span>&gt;
</pre>
<pre data-lang="js" class="notranslate"><span class="hl-property">methods</span>: {
  ...<span class="hl-property">mapMutations</span>([
    <span class="hl-value">&quot;SET_CAMERA_POSITION&quot;</span>,
    <span class="hl-value">&quot;RESET_CAMERA_ROTATION&quot;</span>,
  ]),
  <span class="hl-property">resetCameraPosition</span>() {
    <span class="hl-keyword">this</span>.<span class="hl-property">SET_CAMERA_POSITION</span>({ <span class="hl-property">x</span>: 0, <span class="hl-property">y</span>: 0, <span class="hl-property">z</span>: 500 });
    <span class="hl-keyword">this</span>.<span class="hl-property">RESET_CAMERA_ROTATION</span>();
  },
  <span class="hl-comment">// ...</span>
}
</pre>
<p>Excellent! Everything is turning out very well so far. To wrap things up we will allow the user to manipulate what they see by selectively hiding the content of the scene. We will have two toggles in the control panel: one to control the pyramids and one to control the axis lines. Each will get it's own vuex mutation.</p>
<p>First the axis lines:</p>
<pre data-lang="js" class="notranslate"><span class="hl-property">mutations</span>: {
  <span class="hl-comment">// ..</span>
  <span class="hl-property">HIDE_AXIS_LINES</span>(state) {
    state.<span class="hl-property">scene</span>.<span class="hl-property">remove</span>(...<span class="hl-property">state</span>.<span class="hl-property">axisLines</span>);
    state.<span class="hl-property">renderer</span>.<span class="hl-property">render</span>(state.<span class="hl-property">scene</span>, state.<span class="hl-property">camera</span>);
  },
  <span class="hl-property">SHOW_AXIS_LINES</span>(state) {
    state.<span class="hl-property">scene</span>.<span class="hl-property">add</span>(...<span class="hl-property">state</span>.<span class="hl-property">axisLines</span>);
    state.<span class="hl-property">renderer</span>.<span class="hl-property">render</span>(state.<span class="hl-property">scene</span>, state.<span class="hl-property">camera</span>);
  },
  <span class="hl-comment">// ..</span>
}
</pre>
<p>Next, the pyramids:</p>
<pre data-lang="js" class="notranslate"><span class="hl-property">mutations</span>: {
  <span class="hl-comment">// ...</span>
  <span class="hl-property">HIDE_PYRAMIDS</span>(state) {
    state.<span class="hl-property">scene</span>.<span class="hl-property">remove</span>(...<span class="hl-property">state</span>.<span class="hl-property">pyramids</span>);
    state.<span class="hl-property">renderer</span>.<span class="hl-property">render</span>(state.<span class="hl-property">scene</span>, state.<span class="hl-property">camera</span>);
  },
  <span class="hl-property">SHOW_PYRAMIDS</span>(state) {
    state.<span class="hl-property">scene</span>.<span class="hl-property">add</span>(...<span class="hl-property">state</span>.<span class="hl-property">pyramids</span>);
    state.<span class="hl-property">renderer</span>.<span class="hl-property">render</span>(state.<span class="hl-property">scene</span>, state.<span class="hl-property">camera</span>);
  }
}
</pre>
<p>It is important to note here that we are only able to do this because we are keeping track of the scenery in our application state, separate from the camera and the rendered scene. If we had generated the scenery and used it to render the scene without saving it anywhere this would not be possible.</p>
<p>We can now import these methods into our Control Panel:</p>
<pre data-lang="html" class="notranslate">&lt;<span class="hl-keyword">p</span> <span class="hl-property">class</span>=&quot;mb-1 flex items-center justify-between&quot;&gt;
    Pyramids
    &lt;<span class="hl-keyword">input</span>
        <span class="hl-property">type</span>=&quot;checkbox&quot;
        <span class="hl-property">name</span>=&quot;pyramids&quot;
        <span class="hl-property">id</span>=&quot;pyramids&quot;
        <span class="hl-property">v-model</span>=&quot;pyramidsVisible&quot;
        @<span class="hl-property">click</span>=&quot;togglePyramids&quot;
    /&gt;
&lt;/<span class="hl-keyword">p</span>&gt;
&lt;<span class="hl-keyword">p</span> <span class="hl-property">class</span>=&quot;flex items-center justify-between&quot;&gt;
    Axis Lines
    &lt;<span class="hl-keyword">input</span>
        <span class="hl-property">type</span>=&quot;checkbox&quot;
        <span class="hl-property">name</span>=&quot;axis-lines&quot;
        <span class="hl-property">id</span>=&quot;axis-lines&quot;
        <span class="hl-property">v-model</span>=&quot;axisLinesVisible&quot;
        @<span class="hl-property">click</span>=&quot;toggleAxisLines&quot;
    /&gt;
&lt;/<span class="hl-keyword">p</span>&gt;
</pre>
<pre data-lang="js" class="notranslate"><span class="hl-property">methods</span>: {
  ...<span class="hl-property">mapMutations</span>([
    <span class="hl-value">&quot;SET_CAMERA_POSITION&quot;</span>,
    <span class="hl-value">&quot;RESET_CAMERA_ROTATION&quot;</span>,
    <span class="hl-value">&quot;HIDE_AXIS_LINES&quot;</span>,
    <span class="hl-value">&quot;SHOW_AXIS_LINES&quot;</span>,
    <span class="hl-value">&quot;HIDE_PYRAMIDS&quot;</span>,
    <span class="hl-value">&quot;SHOW_PYRAMIDS&quot;</span>
  ]),
  <span class="hl-property">resetCameraPosition</span>() {
    <span class="hl-keyword">this</span>.<span class="hl-property">SET_CAMERA_POSITION</span>({ <span class="hl-property">x</span>: 0, <span class="hl-property">y</span>: 0, <span class="hl-property">z</span>: 500 });
    <span class="hl-keyword">this</span>.<span class="hl-property">RESET_CAMERA_ROTATION</span>();
  },
  <span class="hl-property">toggleAxisLines</span>() {
    <span class="hl-keyword">if</span> (<span class="hl-keyword">this</span>.<span class="hl-property">axisLinesVisible</span>) {
      <span class="hl-keyword">this</span>.<span class="hl-property">HIDE_AXIS_LINES</span>();
      <span class="hl-keyword">this</span>.<span class="hl-property">axisLinesVisible</span> = <span class="hl-keyword">false</span>;
    } <span class="hl-keyword">else</span> {
      <span class="hl-keyword">this</span>.<span class="hl-property">SHOW_AXIS_LINES</span>();
      <span class="hl-keyword">this</span>.<span class="hl-property">axisLinesVisible</span> = <span class="hl-keyword">true</span>;
    }
  },
  <span class="hl-property">togglePyramids</span>() {
    <span class="hl-keyword">if</span> (<span class="hl-keyword">this</span>.<span class="hl-property">pyramidsVisible</span>) {
      <span class="hl-keyword">this</span>.<span class="hl-property">HIDE_PYRAMIDS</span>();
      <span class="hl-keyword">this</span>.<span class="hl-property">pyramidsVisible</span> = <span class="hl-keyword">false</span>;
    } <span class="hl-keyword">else</span> {
      <span class="hl-keyword">this</span>.<span class="hl-property">SHOW_PYRAMIDS</span>();
      <span class="hl-keyword">this</span>.<span class="hl-property">pyramidsVisible</span> = <span class="hl-keyword">true</span>;
    }
  }
}
</pre>
<p>You have now successfully used Vue, Vuex and Three.js to create and manage a three-dimensional scene in your browser. <a href="https://vuethree.stagerightlabs.com/">You can see this code in action here</a>. This demonstration is somewhat simplistic, but the ideas here should provide a solid foundation for building a more realistic application.</p>
]]>
    </content>
    <link rel="alternate" href="https://stagerightlabs.com/blog/vue-and-threejs-part-two" />
  </entry>
    <entry>
    <title>
      <![CDATA[Vue and Threejs - Part One]]>
    </title>
    <id>tag:stagerightlabs.com,2019-03-19T00:00:00+0000:1552953600</id>
    <updated>2019-03-19T00:00:00+00:00</updated>
    <summary>
      <![CDATA[Three.js is an amazing tool for creating three dimensional layouts in a web application. Let's experiment with integrating Three.js with Vue.js. To start, we will set up Vuex to manage state for our three dimensional content.]]>
    </summary>
    <content type="html">
      <![CDATA[<p>Let's set up a <a href="https://vuejs.org/">Vue</a> application with a three dimensional user experience powered by <a href="https://threejs.org">Three.js</a>.</p>
<p>The completed code for this project is <a href="https://github.com/stagerightlabs/Vue-Three-Demo">available here</a>. You can also check out a <a href="https://vuethree.stagerightlabs.com/">demo</a>. Our goal will be to convert this <a href="https://threejs.org/examples/?q=controls#misc_controls_trackball">Three.js Example</a> into a Vue application, and perhaps add a bit more functionality while we are at it.</p>
<p>To start, spin up a new vue application with the Vue CLI tool. (If you haven't done that before, check out <a href="https://flaviocopes.com/vue-cli/">this great tutorial</a>.) For the sake of this tutorial you can choose any of the settings that you are comfortable with; just make sure you choose to have Vuex added to the project.</p>
<p>Next, we will add Three.js to the project with NPM. You can install it directly via NPM, however it does not yet play nicely with ES6 imports. To get around this, we can use the <code>three-full</code> mirror, which delivers Three.js in a format that is much easier to use with ES6 style imports. Let's install that now:</p>
<pre data-lang="txt" class="notranslate">$ npm install three-full
</pre>
<p>We can now get our development server up and running by using:</p>
<pre data-lang="txt" class="notranslate">$ npm run serve
</pre>
<p>The first thing we will do is remove the <code>HelloWorld.vue</code> file that came with your new application and we will also remove all references to that file from <code>App.vue</code>. We can also remove the default styles from the bottom of the <code>App.vue</code> file and replace them with this:</p>
<pre data-lang="html" class="notranslate">&lt;<span class="hl-keyword">style</span>&gt;<span class="hl-keyword">
    html,
    body </span>{
        <span class="hl-property">width</span>: 100%;
        <span class="hl-property">height</span>: 100%;
        <span class="hl-property">overflow</span>: hidden;
    }<span class="hl-keyword">
    body </span>{
        <span class="hl-property">margin</span>: 0px;
    }<span class="hl-keyword">

    #app </span>{
        <span class="hl-property">height</span>: 100%;
    }
&lt;/<span class="hl-keyword">style</span>&gt;
</pre>
<p>Here we are removing the default padding from the html and body tags and making sure that our #app div will fill the entire visible browser window.</p>
<p>We will use a <code>ViewPort</code> component to manage the canvas element generated by Three.js; let's create that now. Add a new file called <code>ViewPort.vue</code> in your <code>/src/components</code> directory. We can now import that into the main <code>App.vue</code> component. Update the <code>script</code> section in that file to look like this:</p>
<pre data-lang="js" class="notranslate"><span class="hl-keyword">import</span> ViewPort <span class="hl-keyword">from</span> <span class="hl-value">&quot;@/components/ViewPort.vue&quot;</span>;

<span class="hl-keyword">export</span> <span class="hl-keyword">default</span> {
    <span class="hl-property">components</span>: {
        <span class="hl-property">viewport</span>: ViewPort,
    },
};
</pre>
<p>And we can now use that component in our App.vue template:</p>
<pre data-lang="html" class="notranslate">&lt;<span class="hl-keyword">template</span>&gt;
    &lt;<span class="hl-keyword">div</span> <span class="hl-property">id</span>=&quot;app&quot;&gt;
        &lt;<span class="hl-keyword">viewport</span> /&gt;
    &lt;/<span class="hl-keyword">div</span>&gt;
&lt;/<span class="hl-keyword">template</span>&gt;
</pre>
<p>Let's now turn our attention to getting Three.js up and running. Three.js renders three dimensional scenes on canvas elements; before you can render a scene you need to create Camera, Control and Scene objects, that you will then give to a WebGLRender to have the canvas element generated for you. Three.js provides tools for creating all of these objects and populating the scene with three dimensional objects.</p>
<p>We are going to let Vuex manage the various components of our Three.js scene; this will make it much easier for us to modify the scene contents once they have been created, as we will explore in part two. Open your <code>store.js</code> file, and update the top of the file to look like this:</p>
<pre data-lang="js" class="notranslate"><span class="hl-keyword">import</span> Vue <span class="hl-keyword">from</span> <span class="hl-value">&quot;vue&quot;</span>;
<span class="hl-keyword">import</span> Vuex <span class="hl-keyword">from</span> <span class="hl-value">&quot;vuex&quot;</span>;
<span class="hl-keyword">import</span> {
    Scene,
    TrackballControls,
    PerspectiveCamera,
    WebGLRenderer,
    Color,
    FogExp2,
    CylinderBufferGeometry,
    MeshPhongMaterial,
    Mesh,
    DirectionalLight,
    AmbientLight,
    LineBasicMaterial,
    Geometry,
    Vector3,
    Line,
} <span class="hl-keyword">from</span> <span class="hl-value">&quot;three-full&quot;</span>;

<span class="hl-type">Vue</span>.<span class="hl-property">use</span>(Vuex);
</pre>
<p>Here we are importing Vue, Vuex and a litany of Three.js objects that we will use to create our scene. We are going to use vuex mutations to manage the creation of the scenes, and a vuex action to trigger those mutations. The general rule of thumb is that actions are used to handle asynchronous updates, and mutations must always be used for synchronous updates. In a normal Vuex workflow, you might have an action that makes an http request, which would then hand off the response data to mutations to store that data in the vuex state, which is where everything is kept.</p>
<p>Let's start by adding some new items to our state object:</p>
<pre data-lang="js" class="notranslate"><span class="hl-property">state</span>: {
  <span class="hl-property">width</span>: 0,
  <span class="hl-property">height</span>: 0,
  <span class="hl-property">camera</span>: <span class="hl-keyword">null</span>,
  <span class="hl-property">controls</span>: <span class="hl-keyword">null</span>,
  <span class="hl-property">scene</span>: <span class="hl-keyword">null</span>,
  <span class="hl-property">renderer</span>: <span class="hl-keyword">null</span>,
  <span class="hl-property">axisLines</span>: [],
  <span class="hl-property">pyramids</span>: []
},
</pre>
<p>We will use <code>width</code> and <code>height</code> to keep track of the canvas size. <code>camera</code>, <code>controls</code>, <code>scene</code> and <code>renderer</code> will be use to store the tools generated by Three.js. <code>axisLines</code> and <code>pyramids</code> will be used to keep track of the visual elements used in our scene; the scenery if you will.</p>
<p>First up, lets create a mutation that sets the height and width of the canvas. By convention, all vuex method names are upper case:</p>
<pre data-lang="js" class="notranslate"><span class="hl-property">mutations</span>: {
  <span class="hl-property">SET_VIEWPORT_SIZE</span>(state, { width, height }) {
    state.<span class="hl-property">width</span> = width;
    state.<span class="hl-property">height</span> = height;
  },
}
</pre>
<p>Here we are receiving a width and a height and updating the state accordingly. Next, lets create our renderer:</p>
<pre data-lang="js" class="notranslate"><span class="hl-property">mutations</span>: {
  <span class="hl-comment">// ...</span>
  <span class="hl-property">INITIALIZE_RENDERER</span>(state, el) {
    state.<span class="hl-property">renderer</span> = <span class="hl-keyword">new</span> <span class="hl-type">WebGLRenderer</span>({ <span class="hl-property">antialias</span>: <span class="hl-keyword">true</span> });
    state.<span class="hl-property">renderer</span>.<span class="hl-property">setPixelRatio</span>(window.<span class="hl-property">devicePixelRatio</span>);
    state.<span class="hl-property">renderer</span>.<span class="hl-property">setSize</span>(state.<span class="hl-property">width</span>, state.<span class="hl-property">height</span>);
    el.<span class="hl-property">appendChild</span>(state.<span class="hl-property">renderer</span>.<span class="hl-property">domElement</span>);
  },
}
</pre>
<p>Here we are instantiating a new WebGLRenderer (provided by Three.js) and setting the width and height of the scene that we want to create. Note that we this function receives a reference to a dom element (often referred to as <code>el</code>). The WebGLRenderer will create a canvas element for us, but it won't be visible unless we actually add it to the dom tree. <code>el.appendChild</code> adds the canvas element as a child node the <code>el</code> dom element.</p>
<p>Now lets create our camera:</p>
<pre data-lang="js" class="notranslate"><span class="hl-property">mutations</span>: {
  <span class="hl-comment">// ...</span>
  <span class="hl-property">INITIALIZE_CAMERA</span>(state) {
    state.<span class="hl-property">camera</span> = <span class="hl-keyword">new</span> <span class="hl-type">PerspectiveCamera</span>(
      <span class="hl-comment">// 1. Field of View (degrees)</span>
      60,
      <span class="hl-comment">// 2. Aspect ratio</span>
      state.<span class="hl-property">width</span> / state.<span class="hl-property">height</span>,
      <span class="hl-comment">// 3. Near clipping plane</span>
      1,
      <span class="hl-comment">// 4. Far clipping plane</span>
      1000
    );
    state.<span class="hl-property">camera</span>.<span class="hl-property">position</span>.<span class="hl-property">z</span> = 500;
  },
}
</pre>
<p>Here we are creating a new <code>PerspectiveCamera</code> object with four parameters: The field of view of the camera's &quot;lens&quot; in degrees, the aspect ratio of the camera's output, and the &quot;clipping plane&quot; boundaries. Anything further than 1000 units away from the camera will not be visible. Finally, we set the starting position of the camera at 500 units away from origin on the z-axis.</p>
<p>Now lets create our controls:</p>
<pre data-lang="js" class="notranslate"><span class="hl-property">mutations</span>: {
  <span class="hl-comment">// ...</span>
  <span class="hl-property">INITIALIZE_CONTROLS</span>(state) {
    state.<span class="hl-property">controls</span> = <span class="hl-keyword">new</span> <span class="hl-type">TrackballControls</span>(
      state.<span class="hl-property">camera</span>,
      state.<span class="hl-property">renderer</span>.<span class="hl-property">domElement</span>
    );
    state.<span class="hl-property">controls</span>.<span class="hl-property">rotateSpeed</span> = 1.<span class="hl-property">0</span>;
    state.<span class="hl-property">controls</span>.<span class="hl-property">zoomSpeed</span> = 1.<span class="hl-property">2</span>;
    state.<span class="hl-property">controls</span>.<span class="hl-property">panSpeed</span> = 0.<span class="hl-property">8</span>;
    state.<span class="hl-property">controls</span>.<span class="hl-property">noZoom</span> = <span class="hl-keyword">false</span>;
    state.<span class="hl-property">controls</span>.<span class="hl-property">noPan</span> = <span class="hl-keyword">false</span>;
    state.<span class="hl-property">controls</span>.<span class="hl-property">staticMoving</span> = <span class="hl-keyword">true</span>;
    state.<span class="hl-property">controls</span>.<span class="hl-property">dynamicDampingFactor</span> = 0.<span class="hl-property">3</span>;
  },
}
</pre>
<p>Here we instantiate a new <code>TrackballControls</code> object and set up a default configuration for it. The exact nature of this configuration is a bit beyond the scope of this tutorial, but you should feel free to play around with these values and see what happens.</p>
<p>The most important thing to note here is that we are passing in our canvas element as the second argument to the TrackballControls constructor. This will limit the controls to listen only for input events that occur on that dom element. If you don't provide this, it will default to listening to all input events on the entire document which will effectively steal focus away from any other content on the page and translate all input into camera movements in the rendered scene. By limiting this to just the canvas element we will still be able to interact with other content on the page normally.</p>
<p>Next up, the scene content itself. This one is a doozy:</p>
<pre data-lang="js" class="notranslate"><span class="hl-property">mutations</span>: {
  <span class="hl-comment">// ...</span>
  <span class="hl-property">INITIALIZE_SCENE</span>(state) {
    state.<span class="hl-property">scene</span> = <span class="hl-keyword">new</span> <span class="hl-type">Scene</span>();
    state.<span class="hl-property">scene</span>.<span class="hl-property">background</span> = <span class="hl-keyword">new</span> <span class="hl-type">Color</span>(0xcccccc);
    state.<span class="hl-property">scene</span>.<span class="hl-property">fog</span> = <span class="hl-keyword">new</span> <span class="hl-type">FogExp2</span>(0xcccccc, 0.<span class="hl-property">002</span>);
    <span class="hl-keyword">var</span> geometry = <span class="hl-keyword">new</span> <span class="hl-type">CylinderBufferGeometry</span>(0, 10, 30, 4, 1);
    <span class="hl-keyword">var</span> material = <span class="hl-keyword">new</span> <span class="hl-type">MeshPhongMaterial</span>({
      <span class="hl-property">color</span>: 0xffffff,
      <span class="hl-property">flatShading</span>: <span class="hl-keyword">true</span>
    });
    <span class="hl-keyword">for</span> (<span class="hl-keyword">var</span> i = 0; i &lt; 500; i++) {
      <span class="hl-keyword">var</span> mesh = <span class="hl-keyword">new</span> <span class="hl-type">Mesh</span>(geometry, material);
      mesh.<span class="hl-property">position</span>.<span class="hl-property">x</span> = (<span class="hl-type">Math</span>.<span class="hl-property">random</span>() - 0.<span class="hl-property">5</span>) * 1000;
      mesh.<span class="hl-property">position</span>.<span class="hl-property">y</span> = (<span class="hl-type">Math</span>.<span class="hl-property">random</span>() - 0.<span class="hl-property">5</span>) * 1000;
      mesh.<span class="hl-property">position</span>.<span class="hl-property">z</span> = (<span class="hl-type">Math</span>.<span class="hl-property">random</span>() - 0.<span class="hl-property">5</span>) * 1000;
      mesh.<span class="hl-property">updateMatrix</span>();
      mesh.<span class="hl-property">matrixAutoUpdate</span> = <span class="hl-keyword">false</span>;
      state.<span class="hl-property">pyramids</span>.<span class="hl-property">push</span>(mesh);
    }
    state.<span class="hl-property">scene</span>.<span class="hl-property">add</span>(...<span class="hl-property">state</span>.<span class="hl-property">pyramids</span>);

    <span class="hl-comment">// lights</span>
    <span class="hl-keyword">var</span> lightA = <span class="hl-keyword">new</span> <span class="hl-type">DirectionalLight</span>(0xffffff);
    lightA.<span class="hl-property">position</span>.<span class="hl-property">set</span>(1, 1, 1);
    state.<span class="hl-property">scene</span>.<span class="hl-property">add</span>(lightA);
    <span class="hl-keyword">var</span> lightB = <span class="hl-keyword">new</span> <span class="hl-type">DirectionalLight</span>(0x002288);
    lightB.<span class="hl-property">position</span>.<span class="hl-property">set</span>(-1, -1, -1);
    state.<span class="hl-property">scene</span>.<span class="hl-property">add</span>(lightB);
    <span class="hl-keyword">var</span> lightC = <span class="hl-keyword">new</span> <span class="hl-type">AmbientLight</span>(0x222222);
    state.<span class="hl-property">scene</span>.<span class="hl-property">add</span>(lightC);

    <span class="hl-comment">// Axis Line 1</span>
    <span class="hl-keyword">var</span> materialB = <span class="hl-keyword">new</span> <span class="hl-type">LineBasicMaterial</span>({ <span class="hl-property">color</span>: 0x0000ff });
    <span class="hl-keyword">var</span> geometryB = <span class="hl-keyword">new</span> <span class="hl-type">Geometry</span>();
    geometryB.<span class="hl-property">vertices</span>.<span class="hl-property">push</span>(<span class="hl-keyword">new</span> <span class="hl-type">Vector3</span>(0, 0, 0));
    geometryB.<span class="hl-property">vertices</span>.<span class="hl-property">push</span>(<span class="hl-keyword">new</span> <span class="hl-type">Vector3</span>(0, 1000, 0));
    <span class="hl-keyword">var</span> lineA = <span class="hl-keyword">new</span> <span class="hl-type">Line</span>(geometryB, materialB);
    state.<span class="hl-property">axisLines</span>.<span class="hl-property">push</span>(lineA);

    <span class="hl-comment">// Axis Line 2</span>
    <span class="hl-keyword">var</span> materialC = <span class="hl-keyword">new</span> <span class="hl-type">LineBasicMaterial</span>({ <span class="hl-property">color</span>: 0x00ff00 });
    <span class="hl-keyword">var</span> geometryC = <span class="hl-keyword">new</span> <span class="hl-type">Geometry</span>();
    geometryC.<span class="hl-property">vertices</span>.<span class="hl-property">push</span>(<span class="hl-keyword">new</span> <span class="hl-type">Vector3</span>(0, 0, 0));
    geometryC.<span class="hl-property">vertices</span>.<span class="hl-property">push</span>(<span class="hl-keyword">new</span> <span class="hl-type">Vector3</span>(1000, 0, 0));
    <span class="hl-keyword">var</span> lineB = <span class="hl-keyword">new</span> <span class="hl-type">Line</span>(geometryC, materialC);
    state.<span class="hl-property">axisLines</span>.<span class="hl-property">push</span>(lineB);

    <span class="hl-comment">// Axis 3</span>
    <span class="hl-keyword">var</span> materialD = <span class="hl-keyword">new</span> <span class="hl-type">LineBasicMaterial</span>({ <span class="hl-property">color</span>: 0xff0000 });
    <span class="hl-keyword">var</span> geometryD = <span class="hl-keyword">new</span> <span class="hl-type">Geometry</span>();
    geometryD.<span class="hl-property">vertices</span>.<span class="hl-property">push</span>(<span class="hl-keyword">new</span> <span class="hl-type">Vector3</span>(0, 0, 0));
    geometryD.<span class="hl-property">vertices</span>.<span class="hl-property">push</span>(<span class="hl-keyword">new</span> <span class="hl-type">Vector3</span>(0, 0, 1000));
    <span class="hl-keyword">var</span> lineC = <span class="hl-keyword">new</span> <span class="hl-type">Line</span>(geometryD, materialD);
    state.<span class="hl-property">axisLines</span>.<span class="hl-property">push</span>(lineC);

    state.<span class="hl-property">scene</span>.<span class="hl-property">add</span>(...<span class="hl-property">state</span>.<span class="hl-property">axisLines</span>);
  },
}
</pre>
<p>Most of this comes directly from the <a href="https://github.com/mrdoob/three.js/blob/master/examples/misc_controls_trackball.html">Three.js example</a> that we are emulating, however there are couple important differences to note:</p>
<ul>
<li>When we create the pyramid geometries we are storing them in state as an array. This will allow us to make changes to them later on if we want to and then re-render the scene with those changes in place.</li>
<li>We are also adding some straight lines that will follow along each axis of our three dimensional space. This will provide us with a grid of sorts that will help us conceptualize how our three dimensional scene is being rendered. We are also storing these grid lines as an array in state so we can make changes to them later.</li>
</ul>
<p>Next we will create a mutation that will handle resizing the canvas element for us:</p>
<pre data-lang="js" class="notranslate"><span class="hl-property">mutations</span>: {
  <span class="hl-comment">// ...</span>
  <span class="hl-property">RESIZE</span>(state, { width, height }) {
    state.<span class="hl-property">width</span> = width;
    state.<span class="hl-property">height</span> = height;
    state.<span class="hl-property">camera</span>.<span class="hl-property">aspect</span> = width / height;
    state.<span class="hl-property">camera</span>.<span class="hl-property">updateProjectionMatrix</span>();
    state.<span class="hl-property">renderer</span>.<span class="hl-property">setSize</span>(width, height);
    state.<span class="hl-property">controls</span>.<span class="hl-property">handleResize</span>();
    state.<span class="hl-property">renderer</span>.<span class="hl-property">render</span>(state.<span class="hl-property">scene</span>, state.<span class="hl-property">camera</span>);
  },
}
</pre>
<p>This should be pretty straight forward. When we want to resize the canvas we call this mutation and provide it with our new width and height. It then updates the camera and renderer accordingly and re-renders the scene using the new dimensions.</p>
<p>Finally, we will now set up two vuex actions that will orchestrate these various mutations for us. First we will use an action to initialize our scene on page load:</p>
<pre data-lang="js" class="notranslate"><span class="hl-property">actions</span>: {
  <span class="hl-property">INIT</span>({ state, commit }, { width, height, el }) {
    <span class="hl-keyword">return</span> <span class="hl-keyword">new</span> <span class="hl-type">Promise</span>(resolve =&gt; {
      <span class="hl-property">commit</span>(<span class="hl-value">&quot;SET_VIEWPORT_SIZE&quot;</span>, { width, height });
      <span class="hl-property">commit</span>(<span class="hl-value">&quot;INITIALIZE_RENDERER&quot;</span>, el);
      <span class="hl-property">commit</span>(<span class="hl-value">&quot;INITIALIZE_CAMERA&quot;</span>);
      <span class="hl-property">commit</span>(<span class="hl-value">&quot;INITIALIZE_CONTROLS&quot;</span>);
      <span class="hl-property">commit</span>(<span class="hl-value">&quot;INITIALIZE_SCENE&quot;</span>);

      <span class="hl-comment">// Initial scene rendering</span>
      state.<span class="hl-property">renderer</span>.<span class="hl-property">render</span>(state.<span class="hl-property">scene</span>, state.<span class="hl-property">camera</span>);

      <span class="hl-comment">// Add an event listener that will re-render</span>
      <span class="hl-comment">// the scene when the controls are changed</span>
      state.<span class="hl-property">controls</span>.<span class="hl-property">addEventListener</span>(<span class="hl-value">&quot;change&quot;</span>, () =&gt; {
        state.<span class="hl-property">renderer</span>.<span class="hl-property">render</span>(state.<span class="hl-property">scene</span>, state.<span class="hl-property">camera</span>);
      });

      <span class="hl-property">resolve</span>();
    });
  },
}
</pre>
<p>The init function returns a promise that resolves once all of our various Three.js components have been created and registered. It also takes care of the initial scene rendering and sets an event listener that will re-render the scene if the controls receive an input trigger.</p>
<p>Finally, we will use an action to set up our animation loop. This is a recursive function that re-renders the scene (if needed) during every tick of the event loop. We could use <code>setTimeout</code> here, but <code>requestAnimationFrame</code> does the same thing except that it will pause the animation loop if the browser looses focus. <a href="https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame">See more about animation frames here</a>.</p>
<pre data-lang="js" class="notranslate"><span class="hl-property">actions</span>: {
  <span class="hl-comment">// ..</span>
  <span class="hl-property">ANIMATE</span>({ state, dispatch }) {
    window.<span class="hl-property">requestAnimationFrame</span>(() =&gt; {
      <span class="hl-property">dispatch</span>(<span class="hl-value">&quot;ANIMATE&quot;</span>);
      state.<span class="hl-property">controls</span>.<span class="hl-property">update</span>();
    });
  }
}
</pre>
<p>That should cover everything we need to get our 3D scene up and running. Now lets put it all together in our <code>ViewPort</code> component. The template and the styling of this component are very straight forward:</p>
<pre data-lang="html" class="notranslate">&lt;<span class="hl-keyword">template</span>&gt;
    &lt;<span class="hl-keyword">div</span> <span class="hl-property">class</span>=&quot;viewport&quot; /&gt;
&lt;/<span class="hl-keyword">template</span>&gt;
</pre>
<p>We create a single dom node (the root node for this component) which will become a wrapper around the canvas element generated by our WebGLRenderer.</p>
<pre data-lang="html" class="notranslate">&lt;<span class="hl-keyword">style</span>&gt;<span class="hl-keyword">
    .viewport </span>{
        <span class="hl-property">height</span>: 100%;
        <span class="hl-property">width</span>: 100%;
    }
&lt;/<span class="hl-keyword">style</span>&gt;
</pre>
<p>Here we are setting the height and width of the component to be 100% of its parent node, which in this case happens to be the main #app div (the root node of the <code>App.vue</code> component.) This will ensure that our canvas element uses the entire browser screen.</p>
<p>The real fun is in the <code>script</code> section of the component:</p>
<pre data-lang="js" class="notranslate"><span class="hl-keyword">import</span> { mapMutations, mapActions } <span class="hl-keyword">from</span> <span class="hl-value">&quot;vuex&quot;</span>;

<span class="hl-keyword">export</span> <span class="hl-keyword">default</span> {
    <span class="hl-property">data</span>() {
        <span class="hl-keyword">return</span> {
            <span class="hl-property">height</span>: 0,
        };
    },
    <span class="hl-property">methods</span>: {
        ...<span class="hl-property">mapMutations</span>([<span class="hl-value">&quot;RESIZE&quot;</span>]),
        ...<span class="hl-property">mapActions</span>([<span class="hl-value">&quot;INIT&quot;</span>, <span class="hl-value">&quot;ANIMATE&quot;</span>]),
    },
    <span class="hl-property">mounted</span>() {
        <span class="hl-keyword">this</span>.<span class="hl-property">INIT</span>({
            <span class="hl-property">width</span>: <span class="hl-keyword">this</span>.$el.<span class="hl-property">offsetWidth</span>,
            <span class="hl-property">height</span>: <span class="hl-keyword">this</span>.$el.<span class="hl-property">offsetHeight</span>,
            <span class="hl-property">el</span>: <span class="hl-keyword">this</span>.$el,
        }).<span class="hl-property">then</span>(() =&gt; {
            <span class="hl-keyword">this</span>.<span class="hl-property">ANIMATE</span>();
            window.<span class="hl-property">addEventListener</span>(<span class="hl-value">&quot;resize&quot;</span>, () =&gt; {
                <span class="hl-keyword">this</span>.<span class="hl-property">RESIZE</span>({
                    <span class="hl-property">width</span>: <span class="hl-keyword">this</span>.$el.<span class="hl-property">offsetWidth</span>,
                    <span class="hl-property">height</span>: <span class="hl-keyword">this</span>.$el.<span class="hl-property">offsetHeight</span>,
                });
            });
        });
    },
};
</pre>
<p>To start, we import some helper methods from Vuex which will allow us to reference our vuex actions and mutations directly from this component. Next, when the component is mounted (on page load) we will trigger our INIT function, creating our three dimensional scene. When it is ready we will trigger our animation loop and set an event listener that triggers our RESIZE function whenever the browser window is resized.</p>
<p>That should be everything we need! Take a look at the URL being used by your dev server (usually <code>http://localhost:8080/</code>) to see your beautifully rendered scene.</p>
<p>The next installment of this tutorial will investigate creating a control panel that will allow users to manually manipulate the rendered scene.</p>
]]>
    </content>
    <link rel="alternate" href="https://stagerightlabs.com/blog/vue-and-threejs-part-one" />
  </entry>
    <entry>
    <title>
      <![CDATA[Laravel Passport and Travis Ci]]>
    </title>
    <id>tag:stagerightlabs.com,2019-03-02T00:00:00+0000:1551484800</id>
    <updated>2019-03-02T00:00:00+00:00</updated>
    <summary>
      <![CDATA[To use Laravel Passport effectively you need to ensure it is properly configured in your application. Ensuring that this configration also works in a test enviroment can be tricky, depending on your situation. Let's take a look at one possible solution.]]>
    </summary>
    <content type="html">
      <![CDATA[<p>When using Laravel Passport in a project that uses Travis for continuous integration, it is important to make sure that the testing environment on travis is configured properly, otherwise you may encounter errors that will prevent your build from passing.</p>
<ul class="table-of-contents">
<li><a href="#the-travisyml-file">The .travis.yml file</a></li>
<li><a href="#the-env-configuration-file">The .env configuration file</a></li>
<li><a href="#the-phpunitxml-file">The phpunit.xml file</a></li>
</ul>
<h2><a id="the-travisyml-file" href="#the-travisyml-file" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>The .travis.yml file</h2>
<p>After some trial and error, I have come up with a working <code>.travis.yml</code> configuration.</p>
<pre data-lang="yaml" class="notranslate"><span class="hl-comment"># .travis.yml</span>
<span class="hl-keyword">language</span><span class="hl-property">:</span> php

<span class="hl-keyword">php</span><span class="hl-property">:</span>
    <span class="hl-property">-</span> 7.1
    <span class="hl-property">-</span> 7.2

<span class="hl-keyword">before_script</span><span class="hl-property">:</span>
    <span class="hl-property">-</span> travis_retry composer self-update
    <span class="hl-property">-</span> travis_retry composer install --prefer-source --no-interaction --no-suggest
    <span class="hl-property">-</span> cp .env.travis .env
    <span class="hl-property">-</span> php artisan <span class="hl-keyword">key</span><span class="hl-property">:</span>generate
    <span class="hl-property">-</span> php artisan migrate
    <span class="hl-property">-</span> php artisan <span class="hl-keyword">passport</span><span class="hl-property">:</span>keys

<span class="hl-keyword">script</span><span class="hl-property">:</span>
    <span class="hl-property">-</span> vendor/bin/phpunit

<span class="hl-keyword">sudo</span><span class="hl-property">:</span> false
</pre>
<p>The first two sections are self-explanatory. We are going to be testing a PHP project, and we want Travis to test our code against PHP 7.1 and 7.2.</p>
<p>The <code>before_script</code> section is where we outline how we want the testing environment to be prepared before the tests are run. Lets break this down line by line:</p>
<ul>
<li><code>travis_retry composer self-update</code> <br />Here we are ensuring that we have the latest version of composer available to us in our testing container.</li>
<li><code>travis_retry composer install --prefer-source --no-interaction --no-suggest</code> <br /> Here we install the package dependencies outlined in the <code>composer.lock</code> file that lives in our project repo.</li>
<li><code>cp .env.travis .env</code> <br /> We will use a specially crafted <code>.env</code> file to ensure that the application being tested is configured correctly for this testing environment. See below for more details.</li>
<li><code>php artisan key:generate</code> <br /> Here we will generate a hashing key that will be used for the lifetime of this test run. The Laravel framework uses this value internally, so you should always generate a key even if you are not explicitly creating hashes in your application.</li>
<li><code>php artisan migrate</code> <br /> Here we are running the database migrations to create the DB structure that the application is expecting. I opted to publish the Passport migrations directly to my <code>database/migrations</code> folder, rather than registering them separately. Regardless, these migrations include the tables that Passport uses to store its client data. It is also important to note that the project has been configured to use an in-memory sqlite database, which is why we don't have to create an empty database during these provisioning steps.</li>
<li><code>php artisan passport:keys</code> <br /> This is the most important step. Here we are asking Passport to generate the RSA keys that it uses to generate its grants. By default these keys are stored in the <code>storage/</code> directory.</li>
</ul>
<p>The <code>script</code> section is where we tell Travis how to run our tests. Note that I am specifying that I want travis to use the version of PHPUnit that was installed via Composer, rather than the global version that it makes available to us in the container. This way I can always know for sure exactly which version of PHPUnit I am running, and we can run a newer version if we want to.</p>
<p>The last section, <code>sudo: false</code>, is how we tell Travis to run our tests in a containerized environment. This often means that our tests will run faster (though not always.). The downside is that we don't have <code>sudo</code> available to us when provisioning. If we were to need that option we would have to use the slower, non-container environment that Travis offers.</p>
<h2><a id="the-env-configuration-file" href="#the-env-configuration-file" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>The .env configuration file</h2>
<p>This is the special <code>.env.travis</code> file I used to specify application specific testing configuration:</p>
<pre data-lang="dotenv" class="notranslate"><span class="hl-keyword">APP_NAME</span>=ExampleLaravelApplication
<span class="hl-keyword">APP_ENV</span>=local
<span class="hl-keyword">APP_KEY</span>=
<span class="hl-keyword">APP_DEBUG</span>=true
<span class="hl-keyword">APP_LOG_LEVEL</span>=debug
<span class="hl-keyword">APP_URL</span>=http://localhost

<span class="hl-keyword">DB_CONNECTION</span>=sqlite
<span class="hl-keyword">DB_DATABASE</span>=:memory:
<span class="hl-keyword">DB_USERNAME</span>=homestead
<span class="hl-keyword">DB_PASSWORD</span>=secret

<span class="hl-keyword">BROADCAST_DRIVER</span>=log
<span class="hl-keyword">CACHE_DRIVER</span>=file
<span class="hl-keyword">SESSION_DRIVER</span>=file
<span class="hl-keyword">SESSION_LIFETIME</span>=120
<span class="hl-keyword">QUEUE_DRIVER</span>=sync

<span class="hl-keyword">REDIS_HOST</span>=127.0.0.1
<span class="hl-keyword">REDIS_PASSWORD</span>=null
<span class="hl-keyword">REDIS_PORT</span>=6379

<span class="hl-keyword">MAIL_DRIVER</span>=log
<span class="hl-keyword">MAIL_HOST</span>=smtp.mailtrap.io
<span class="hl-keyword">MAIL_PORT</span>=2525
<span class="hl-keyword">MAIL_USERNAME</span>=null
<span class="hl-keyword">MAIL_PASSWORD</span>=null
<span class="hl-keyword">MAIL_ENCRYPTION</span>=null
</pre>
<p>The most important option here is the <code>DB_DATABASE=:memory:</code> option. This tells the application that we want to use an in-memory sqlite database. Even though the <code>APP_ENV</code> is &quot;local&quot; here, it will be over-written by the ENV values specified in the <code>phpunit.xml</code> file. This is where we set the application environment to &quot;testing&quot; for the lifetime of the test run.</p>
<h2><a id="the-phpunitxml-file" href="#the-phpunitxml-file" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>The phpunit.xml file</h2>
<p>We also set some importan environment variables in the <code>phpunit.xml</code> file:</p>
<pre data-lang="xml" class="notranslate">&lt;?xml <span class="hl-property">version</span>=&quot;1.0&quot; <span class="hl-property">encoding</span>=&quot;UTF-8&quot;?&gt;
&lt;<span class="hl-keyword">phpunit</span> <span class="hl-property">backupGlobals</span>=&quot;false&quot;
         <span class="hl-property">backupStaticAttributes</span>=&quot;false&quot;
         <span class="hl-property">bootstrap</span>=&quot;vendor/autoload.php&quot;
         <span class="hl-property">colors</span>=&quot;true&quot;
         <span class="hl-property">convertErrorsToExceptions</span>=&quot;true&quot;
         <span class="hl-property">convertNoticesToExceptions</span>=&quot;true&quot;
         <span class="hl-property">convertWarningsToExceptions</span>=&quot;true&quot;
         <span class="hl-property">processIsolation</span>=&quot;false&quot;
         <span class="hl-property">stopOnFailure</span>=&quot;false&quot;&gt;
    &lt;<span class="hl-keyword">testsuites</span>&gt;
        &lt;<span class="hl-keyword">testsuite</span> <span class="hl-property">name</span>=&quot;Feature&quot;&gt;
            &lt;<span class="hl-keyword">directory</span> <span class="hl-property">suffix</span>=&quot;Test.php&quot;&gt;./tests/Feature&lt;/<span class="hl-keyword">directory</span>&gt;
        &lt;/<span class="hl-keyword">testsuite</span>&gt;

        &lt;<span class="hl-keyword">testsuite</span> <span class="hl-property">name</span>=&quot;Unit&quot;&gt;
            &lt;<span class="hl-keyword">directory</span> <span class="hl-property">suffix</span>=&quot;Test.php&quot;&gt;./tests/Unit&lt;/<span class="hl-keyword">directory</span>&gt;
        &lt;/<span class="hl-keyword">testsuite</span>&gt;
    &lt;/<span class="hl-keyword">testsuites</span>&gt;
    &lt;<span class="hl-keyword">filter</span>&gt;
        &lt;<span class="hl-keyword">whitelist</span> <span class="hl-property">processUncoveredFilesFromWhitelist</span>=&quot;true&quot;&gt;
            &lt;<span class="hl-keyword">directory</span> <span class="hl-property">suffix</span>=&quot;.php&quot;&gt;./app&lt;/<span class="hl-keyword">directory</span>&gt;
        &lt;/<span class="hl-keyword">whitelist</span>&gt;
    &lt;/<span class="hl-keyword">filter</span>&gt;
    &lt;<span class="hl-keyword">php</span>&gt;
        &lt;<span class="hl-keyword">env</span> <span class="hl-property">name</span>=&quot;APP_ENV&quot; <span class="hl-property">value</span>=&quot;testing&quot;/&gt;
        &lt;<span class="hl-keyword">env</span> <span class="hl-property">name</span>=&quot;CACHE_DRIVER&quot; <span class="hl-property">value</span>=&quot;array&quot;/&gt;
        &lt;<span class="hl-keyword">env</span> <span class="hl-property">name</span>=&quot;SESSION_DRIVER&quot; <span class="hl-property">value</span>=&quot;array&quot;/&gt;
        &lt;<span class="hl-keyword">env</span> <span class="hl-property">name</span>=&quot;QUEUE_DRIVER&quot; <span class="hl-property">value</span>=&quot;sync&quot;/&gt;
        &lt;<span class="hl-keyword">env</span> <span class="hl-property">name</span>=&quot;DB_CONNECTION&quot; <span class="hl-property">value</span>=&quot;testing&quot; /&gt;
        &lt;<span class="hl-keyword">env</span> <span class="hl-property">name</span>=&quot;PASSPORT_CLIENT_SECRET&quot; <span class="hl-property">value</span>=&quot;Dtg9myGAIsTUbTck2kxrxeZ5TDnE1qbVvTeYIuPN&quot; /&gt;
    &lt;/<span class="hl-keyword">php</span>&gt;
&lt;/<span class="hl-keyword">phpunit</span>&gt;
</pre>
<p>There are two important things to note about this file:</p>
<ul>
<li>We set the <code>APP_ENV</code> environment variable to &quot;testing&quot;. This puts our Laravel application into testing mode, which disables certain features like CSRF checks; which can be annoying to deal with when testing.</li>
<li>Secondly, we are setting a random value as our <code>PASSPORT_CLIENT_SECRET</code> value. This value matches the oauth secret used in our test fixtures when we create simulated Password Clients for our authentication tests. The application I am testing uses an environment variable to store the ID of the password grant client we use to decode Json Web Tokens; we want to simulate that in our testing environment. You may not need to do this if you are using Passport differently.</li>
</ul>
<p>Thats it! Once you understand how the pieces fit together it is not as complex as it first seems.</p>
]]>
    </content>
    <link rel="alternate" href="https://stagerightlabs.com/blog/laravel-passport-and-travis-ci" />
  </entry>
    <entry>
    <title>
      <![CDATA[Using Tailwind With Sass, Vue-Cli and Webpack]]>
    </title>
    <id>tag:stagerightlabs.com,2017-12-18T00:00:00+0000:1513555200</id>
    <updated>2017-12-18T00:00:00+00:00</updated>
    <summary>
      <![CDATA[TailwindCSS is an amazing new front-end framework based entirely on the use of "utility" classes. Let's take a look at setting up a new project with TailwindCSS, SASS, WebPack and the Vue CLI.]]>
    </summary>
    <content type="html">
      <![CDATA[<p>I recently decided to revamp my personal home page as a Vue SPA. I am not much of a designer, so I am going to use a free design from <a href="https://html5up.net/">HTML5 Up!</a> as a starting point and riff from there. Most of those templates make heavy use of Sass - of which I am a big fan. Theoretically you can use PostCSS plugins to replicate everything that SASS does, but I am not ready to make that leap yet. Perhaps someday. So, my plan is to use the Vue CLI webpack starter template along with an HTML5 Up design as the foundation for my new site.</p>
<p>Just to mix things up, I thought I would also try taking <a href="https://tailwindcss.com/">Tailwind CSS</a> for a spin as well. I may have to re-work quite a bit of the design template to integrate it with the Tailwind framework, but if it works it will be worth the effort.</p>
<p>Here are the steps I took to get my dev setup up and running:</p>
<p>Start by <a href="https://github.com/vuejs/vue-cli">installing</a> the Vue CLI tool and then using it to generate a new site:</p>
<pre data-lang="txt" class="notranslate">$ vue init webpack homepage
</pre>
<p>I used all the default answers to the prompts, and I had Vue CLI run <code>npm install</code> for me. Next, after moving my terminal session into the new project directory, I installed Sass and Tailwind CSS:</p>
<pre data-lang="txt" class="notranslate">$ npm install node-sass sass-loader tailwindcss --save-dev
</pre>
<p>and then I initialized my new <code>tailwind.js</code> configuration file:</p>
<pre data-lang="txt" class="notranslate">$ ./node_modules/.bin/tailwind init tailwind.js
</pre>
<p>We also need to update the <code>.postcssrc.js</code> file to have Post CSS trigger the tailwind compliation step:</p>
<pre data-lang="js" class="notranslate">module.<span class="hl-property">exports</span> = {
    <span class="hl-property">plugins</span>: [<span class="hl-property">require</span>(<span class="hl-value">&quot;tailwindcss&quot;</span>)(<span class="hl-value">&quot;tailwind.js&quot;</span>), <span class="hl-property">require</span>(<span class="hl-value">&quot;autoprefixer&quot;</span>)()],
};
</pre>
<p>Now everything has been installed, we just need to get it all working together. Start by creating an <code>app.scss</code> file in a new <code>/src/assets/scss/</code> directory, and then pasting in the tailwind base directives. In the example below I have removed the comments to save space.</p>
<pre data-lang="txt" class="notranslate">@tailwind preflight;

/* Custom Sass goes here... */

@tailwind utilities;
</pre>
<p>Next, locate the &quot;style&quot; section in the <code>App.vue</code> file and replace it with this:</p>
<pre data-lang="html" class="notranslate">&lt;<span class="hl-keyword">style</span> <span class="hl-property">lang</span>=&quot;sass&quot;&gt;
    @import &quot;./assets/scss/app.scss&quot;
&lt;/<span class="hl-keyword">style</span>&gt;
</pre>
<p>Note that when using Sass with the Vue Style loader (which allows for using Sass in Vue Component files) you have to be specific here about which type of sass files you will be using. If you specify <code>lang=&quot;scss&quot;</code> the loader will assume you are using the &quot;indentation&quot; style of sass files, whereas <code>lang=&quot;sass&quot;</code> will indicate the use of bracket style sass files.</p>
<p>At this point, you should be able to run <code>npm run dev</code> to compile the assets and launch a dev server.</p>
<p>To verify that everything is working, try updating your app.scss file to look like this:</p>
<pre data-lang="txt" class="notranslate">@tailwind preflight;

#app {
    @apply .text-center .text-grey-darker .mt-8;
    font-family: &quot;Avenir&quot;, Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

@tailwind utilities;
</pre>
<p>If everything is working correctly, wepback will automatically recompile that file and refresh the dev server content, and you should see that we are now successfully using Tailwind CSS directives to manipulate the content on the home page.</p>
]]>
    </content>
    <link rel="alternate" href="https://stagerightlabs.com/blog/using-tailwind-with-sass-vue-cli-and-webpack" />
  </entry>
    <entry>
    <title>
      <![CDATA[Simplify Validation Messaging With Blade Directives]]>
    </title>
    <id>tag:stagerightlabs.com,2017-11-15T00:00:00+0000:1510704000</id>
    <updated>2017-11-15T00:00:00+00:00</updated>
    <summary>
      <![CDATA[Displaying error messages can be a cumbersome affair, especially if you don't want to use the default message format. Let's use a custom blade directive to simplify how we show validation errors to users.]]>
    </summary>
    <content type="html">
      <![CDATA[<p>I am a big fan of templating tools, and Laravel's <a href="https://laravel.com/docs/5.5/blade">Blade</a> templating system in particular. Given that PHP itself was originally conceived as a templating language you might think that using an additional layer of templating on top of PHP is a bit ironic, but I do think there is a real benefit. We as developers often get caught up in the details of the applications we are building and can sometimes forget that these applications will (hopefully) have a lifespan that goes beyond the work of a single developer. Anything we can do to simplify the cognitive overhead required to bring new developers on-board will go a long way towards keeping our codebase alive and healthy. When used correctly, templating systems like Twig, Mustache or Blade can be a very effective for this purpose.</p>
<p>As you may know, the form data validation provided by Laravel is very powerful and robust. However, it occurred to me the other day that there is one area that still feels a bit messy and overly complicated. When displaying error messages to users, some developers prefer to show all of the error messages at the top of the form - this is very easy to do and Laravel makes it a snap to implement. However, other developers prefer to show the errors within the body of the form, so that each message appears next to its corresponding input. To do that, you have to set up your form inputs to look something like this:</p>
<pre data-lang="html" class="notranslate">&lt;<span class="hl-keyword">div</span> <span class="hl-property">class</span>=&quot;form-group&quot;&gt;
    &lt;<span class="hl-keyword">label</span> <span class="hl-property">for</span>=&quot;input-title&quot;&gt;Title&lt;/<span class="hl-keyword">label</span>&gt;
    &lt;<span class="hl-keyword">input</span>
        <span class="hl-property">type</span>=&quot;text&quot;
        <span class="hl-property">name</span>=&quot;title&quot;
        <span class="hl-property">class</span>=&quot;form-control {{ $errors-&gt;has('title') ? 'is-invalid' : '' }}&quot;
        <span class="hl-property">id</span>=&quot;input-title&quot;
    /&gt;
    {!! $errors-&gt;has('subtitle') ? $errors-&gt;first('subtitle', '
    &lt;<span class="hl-keyword">div</span> <span class="hl-property">class</span>=&quot;invalid-feedback&quot;&gt;:message&lt;/<span class="hl-keyword">div</span>&gt;
    ') : '' !!}
&lt;/<span class="hl-keyword">div</span>&gt;
</pre>
<p>In this example, which makes use of Bootstrap 4, we first check the <code>$errors</code> Message Bag to see if this input has any messages available. If so, we add the <code>is-invalid</code> class to the input. After that we check the errors again to see if this input has any messages, and then we display that message. By default, the messages are delivered back as plain text, but by passing in a formatting method we get back the message as html formatted as indicated. This is very handy when working within a CSS framework that has specific requirements about how validation messages should be displayed.</p>
<p>This feels messy to me. There is a lot going on there, and having to specify the message format repeatedly for each input on the form seems needlessly redundant. How can we simplify this? How about a custom <a href="https://laravel.com/docs/5.5/blade#extending-blade">blade directive</a>?</p>
<p>Add this to your <code>AppServiceProvider</code> (or any place that is loaded before views are rendered):</p>
<pre data-lang="php" class="notranslate"><span class="hl-comment">// AppServiceProvider.php</span>
<span class="hl-type">Blade</span>::<span class="hl-property">directive</span>(<span class="hl-value">'error'</span>, <span class="hl-keyword">function</span>(<span class="hl-injection">$key</span>) {
    <span class="hl-variable">$key</span> = <span class="hl-property">str_replace</span>([<span class="hl-value">'\''</span>, <span class="hl-value">'&quot;'</span>], <span class="hl-value">''</span>, <span class="hl-variable">$key</span>);
    <span class="hl-variable">$errors</span> = <span class="hl-property">session</span>()-&gt;<span class="hl-property">get</span>(<span class="hl-value">'errors'</span>) ?: <span class="hl-keyword">new</span> <span class="hl-type">\Illuminate\Support\ViewErrorBag</span>;

    <span class="hl-keyword">if</span> (<span class="hl-variable">$message</span> = <span class="hl-variable">$errors</span>-&gt;<span class="hl-property">first</span>(<span class="hl-variable">$key</span>)) {
        <span class="hl-keyword">return</span> <span class="hl-value">&quot;&lt;?php echo '&lt;div class=\&quot;invalid-feedback\&quot;&gt;{$message}&lt;/div&gt;'; ?&gt;&quot;</span>;
    }
});
</pre>
<p>This allows us to simplify our input like so:</p>
<pre data-lang="html" class="notranslate">&lt;<span class="hl-keyword">div</span> <span class="hl-property">class</span>=&quot;form-group&quot;&gt;
    &lt;<span class="hl-keyword">label</span> <span class="hl-property">for</span>=&quot;input-title&quot;&gt;Title&lt;/<span class="hl-keyword">label</span>&gt;
    &lt;<span class="hl-keyword">input</span>
        <span class="hl-property">type</span>=&quot;text&quot;
        <span class="hl-property">name</span>=&quot;title&quot;
        <span class="hl-property">class</span>=&quot;form-control {{ $errors-&gt;has('title') ? 'is-invalid' : '' }}&quot;
        <span class="hl-property">id</span>=&quot;input-title&quot;
    /&gt;
    @error('title')
&lt;/<span class="hl-keyword">div</span>&gt;
</pre>
<p>We have wrapped up our error message display logic a single reusable bundle. When we receive the key from the blade compiler it is delivered as a raw string that includes the single quotes, like so: <code>'title'</code>. The first step is stripping out the quotation marks. After that we resolve the error message bag out of the session. If there is no message bag available we new one up instead. After that we return the content of the validation message formatted, in this case, for Bootstrap 4.</p>
<p>This is all well and good, but I think we can take it one step further. Most applications have a helpers file for collecting utility functions. (I am a big fan of <a href="https://stackoverflow.com/a/28360186">this technique</a>.) If you have one available, toss this in there:</p>
<pre data-lang="php" class="notranslate"><span class="hl-comment">// helpers.php</span>
<span class="hl-keyword">if</span> (! <span class="hl-property">function_exists</span>(<span class="hl-injection">'hasError')</span>) {
    <span class="hl-comment">/**
     * Check for the existence of an error message and return a class name
     *
     * <span class="hl-value">@param</span>  <span class="hl-type">string </span> <span class="hl-variable">$key</span>
     * <span class="hl-value">@return</span> <span class="hl-type">string</span>
     */</span>
    <span class="hl-keyword">function</span> <span class="hl-property">hasError</span>(<span class="hl-injection">$key</span>)
    {
        <span class="hl-variable">$errors</span> = <span class="hl-property">session</span>()-&gt;<span class="hl-property">get</span>(<span class="hl-value">'errors'</span>) ?: <span class="hl-keyword">new</span> <span class="hl-type">\Illuminate\Support\ViewErrorBag</span>;

        <span class="hl-keyword">return</span> <span class="hl-variable">$errors</span>-&gt;<span class="hl-property">has</span>(<span class="hl-variable">$key</span>) <span class="hl-operator">?</span> <span class="hl-value">'is-invalid'</span> : <span class="hl-value">''</span>;
    }
}
</pre>
<p>It would be nice to set this up as a blade directive as well but because we want to keep it on the same line as the input tag itself, a blade directive is not an option; a helper function makes more sense. I am not quite sure that <code>hasError</code> is the right name for this - if you have any inspired ideas let me know in the comments. Regardless, with that method in place, we can now update our input like so:</p>
<pre data-lang="html" class="notranslate">&lt;<span class="hl-keyword">div</span> <span class="hl-property">class</span>=&quot;form-group&quot;&gt;
    &lt;<span class="hl-keyword">label</span> <span class="hl-property">for</span>=&quot;input-title&quot;&gt;Title&lt;/<span class="hl-keyword">label</span>&gt;
    &lt;<span class="hl-keyword">input</span>
        <span class="hl-property">type</span>=&quot;text&quot;
        <span class="hl-property">name</span>=&quot;title&quot;
        <span class="hl-property">class</span>=&quot;form-control {{ hasError('title')  }}&quot;
        <span class="hl-property">id</span>=&quot;input-title&quot;
    /&gt;
    @error('title')
&lt;/<span class="hl-keyword">div</span>&gt;
</pre>
<p>This feels much cleaner to me.</p>
<p>It is important to note that by using this blade directive we are not actually changing how messages are displayed - the methodology remains the same. All we are doing is isolating some of the clutter in the template file and hopefully making it easier to read and understand by future developers.</p>
<p>While we are at it, there is one more custom directive you might find useful:</p>
<pre data-lang="php" class="notranslate"><span class="hl-comment">// AppServiceProvider.php</span>
<span class="hl-type">Blade</span>::<span class="hl-property">directive</span>(<span class="hl-value">'errors'</span>, <span class="hl-keyword">function</span>() {
    <span class="hl-variable">$errors</span> = <span class="hl-property">session</span>()-&gt;<span class="hl-property">get</span>(<span class="hl-value">'errors'</span>) ?: <span class="hl-keyword">new</span> <span class="hl-type">\Illuminate\Support\ViewErrorBag</span>;
    <span class="hl-keyword">return</span> <span class="hl-value">&quot;&lt;?php echo '&lt;pre&gt;&quot;</span> . <span class="hl-property">print_r</span>(<span class="hl-variable">$errors</span>-&gt;<span class="hl-property">getMessages</span>(), <span class="hl-keyword">true</span>) . <span class="hl-value">&quot;&lt;/pre&gt;'; ?&gt;&quot;</span>;
});
</pre>
<p>This is a utility method for quickly echoing all of the currently available error messages to the screen, when used like this:</p>
<pre data-lang="txt" class="notranslate">@errors
</pre>
<p>If you ever find yourself with a form that is not passing validation but no error messages are being displayed, this tool can tell you if there are any messages not being displayed.</p>
<p>You might think that these ideas would be good candidates for inclusion in the Laravel Framework directly, but I disagree. If these were provided by the framework they would be much harder to customize between applications, requiring more layers of code and cognitive overhead to keep working properly. It is much simpler to just toss them in to an application when needed and customize them directly. No muss no fuss. This is exactly why Taylor set up the ability to create custom Blade directives in the first place.</p>
<p>If you run into any trouble adding this to your project, remember that the docs recommend flushing your view cache any time you edit your blade directives, via <code>php artisan view:clear</code>.</p>
]]>
    </content>
    <link rel="alternate" href="https://stagerightlabs.com/blog/simplify-validation-messaging-with-blade-directives" />
  </entry>
    <entry>
    <title>
      <![CDATA[Better 404 Logging in Laravel]]>
    </title>
    <id>tag:stagerightlabs.com,2017-03-17T00:00:00+0000:1489708800</id>
    <updated>2017-03-17T00:00:00+00:00</updated>
    <summary>
      <![CDATA[We can use Laravel's error handling tools to write log entries when users trigger 404 errors. This can help us track down broken links or find other potential problems with the user experience in our Laravel application.]]>
    </summary>
    <content type="html">
      <![CDATA[<p>Out of the box, Laravel provides an excellent methodology for handling exceptions that occur in your applications. However, I sometimes find that the default handling of 404 errors is not very helpful for resolving problematic URLs. It turns out this is very easy to implement with a few minor tweaks.</p>
<p>Every Laravel 5.* has an <code>App/Exceptions/Handler</code> class that allows us to customize how exceptions are reported and how they are displayed to the user (<a href="https://laravel.com/docs/5.4/errors#the-exception-handler">More info here</a>.) This class extends a framework class called <code>Illuminate\Foundation\Exceptions\Handler</code> which is where most of the specifics of how errors are handled can be found. In our application <code>Handler</code> class, there are two key methods: <code>report()</code> and <code>render()</code>. As the documentation tells us, the render method determines how an exception should be shown to a user. This is important because we want to be able to display an error in a way that makes the most sense for the context in which it was encountered. An ajax call will most likely want a json response, whereas an http call will want an html response. A command line exception might want something completely different. The default reporting method most likely already does 99% of what you might want it to do.</p>
<p>For now, we are more interested in the <code>report()</code> method. This method is specifically intended as a tool for customizing how we log errors. By default, Laravel disables the reporting of Http errors (such as 404) by including <code>Symfony\Component\HttpKernel\Exception\HttpException::class</code> in the <code>$dontReport</code> list. We could just comment out that line, but that won't actually help us accomplish our goal. When a 404 error is handled to the logger, you get something like this:</p>
<pre data-lang="txt" class="notranslate">[2017-03-17 22:51:00] local.ERROR: Symfony\Component\HttpKernel\Exception\NotFoundHttpException in /home/vagrant/example.com/vendor/laravel/framework/src/Illuminate/Routing/RouteCollection.php:161
Stack trace:
#0 /home/vagrant/example.com/vendor/laravel/framework/src/Illuminate/Routing/Router.php(533): Illuminate\Routing\RouteCollection-&gt;match(Object(Illuminate\Http\Request))
... lots of other stuff ...
#14 /home/vagrant/example.com/public/index.php(53): Illuminate\Foundation\Http\Kernel-&gt;handle(Object(Illuminate\Http\Request))
</pre>
<p>Which doesn't actually tell us what url has caused the problem. Instead, lets update our custom <code>report()</code> method to give us more details:</p>
<pre data-lang="php" class="notranslate"><span class="hl-keyword">use</span> <span class="hl-type">Symfony\Component\HttpKernel\Exception\NotFoundHttpException</span>;

<span class="hl-comment">//...</span>

<span class="hl-keyword">public</span> <span class="hl-keyword">function</span> <span class="hl-property">report</span>(<span class="hl-injection"><span class="hl-type">Exception</span> $exception</span>)
{
    <span class="hl-keyword">if</span> (<span class="hl-variable">$exception</span> <span class="hl-keyword">instanceof</span> <span class="hl-type">NotFoundHttpException</span> <span class="hl-operator">&amp;&amp;</span> <span class="hl-variable">$request</span> = <span class="hl-property">request</span>()) {
        <span class="hl-type">Bugsnag</span>::<span class="hl-property">notifyError</span>(<span class="hl-value">'404'</span>, <span class="hl-value">'Page Not Found'</span>, <span class="hl-keyword">function</span> (<span class="hl-injection">$report) </span><span class="hl-keyword">use</span> (<span class="hl-variable">$request</span>) {
            <span class="hl-variable">$report</span>-&gt;<span class="hl-property">setSeverity</span>(<span class="hl-value">'info'</span>);
            <span class="hl-variable">$report</span>-&gt;<span class="hl-property">setMetaData</span>([
                <span class="hl-value">'url'</span> =&gt; <span class="hl-variable">$request</span>-&gt;<span class="hl-property">url</span>()
            ]);
        });
    }

    <span class="hl-keyword">parent</span>::<span class="hl-property">report</span>(<span class="hl-variable">$exception</span>);
}
</pre>
<p>Here we check the exception type before handing it off to the parent class report() method. If it is an instance of <code>NotFoundHttpException</code> and we have access to a valid request object, we log the url that has caused the problem. I am using Bugsnag in this example, but you could just as easily use another service or the default Monolog logger that Laravel provides. The main benefit to this method is that it allows us to log exactly the information we are looking for in whatever way we want to.</p>
<p><code>NotFoundHttpException</code> is a <a href="http://api.symfony.com/2.3/Symfony/Component/HttpKernel/Exception/NotFoundHttpException.html">Symfony class</a> that represents a 404 error. Laravel uses the Symfony Http handler behind the scenes. There are lots of features in Laravel that are provided by the Symfony classes used by Laravel, and most of the are essentially undocumented - at least within the Laravel ecosphere. I highly recommend digging into the source code where you can to discover helpful gems and insights.</p>
]]>
    </content>
    <link rel="alternate" href="https://stagerightlabs.com/blog/better-404-logging-in-laravel" />
  </entry>
    <entry>
    <title>
      <![CDATA[Using Mockery With Codeception and Laravel 4]]>
    </title>
    <id>tag:stagerightlabs.com,2015-11-30T00:00:00+0000:1448841600</id>
    <updated>2015-11-30T00:00:00+00:00</updated>
    <summary>
      <![CDATA[Integrating Codeception with a Laravel 4.* application is not as straight forward as you might hope, especially if you need to mock API calls. Let's take a look at an approach I used recently that solved this problem.]]>
    </summary>
    <content type="html">
      <![CDATA[<p>I have a new client who came to me wanting to build out some new features on an existing Laravel 4.2 application. Unfortunately the codebase did not have any tests, which complicates the process of implementing the new changes. As a sort of stop-gap measure, we have agreed to add some &quot;retro-active&quot; acceptance tests to make sure that the existing functionality isn't inadvertently broken.</p>
<p>Being on 4.2, it does not have access to all of the great testing conveniences found in Laravel 5.*, which is unfortunate because it means I didn't have access to any of the new test helpers. Codeception is a great alternative testing package that provides a wealth of functionality and it is already compatible with Laravel 4 - this seemed like the best choice for us. So far, it has been working quite well for us, but I did run into one particularly frustrating problem: Binding mocks of service classes to the IoC does not work &quot;out of the box&quot;. This is frustrating if you have a service class that hits a third-party API and you don't want to have to hit that API each time you run your tests.</p>
<p>As it turns out, this problem is due to the Laravel4 Module re-initializing the Application object on each request. While it looks like this should work, it actually doesn't:</p>
<pre data-lang="php" class="notranslate"><span class="hl-variable">$I</span> = <span class="hl-keyword">new</span> <span class="hl-type">FunctionalTester</span>(<span class="hl-variable">$scenario</span>);

<span class="hl-variable">$I</span>-&gt;<span class="hl-property">wantTo</span>(<span class="hl-value">'upgrade a subscription plan'</span>);

<span class="hl-variable">$I</span>-&gt;<span class="hl-property">amActingAs</span>(<span class="hl-value">'testuser@example.com'</span>); <span class="hl-comment">// This is a custom helper method which sets the active user</span>

<span class="hl-comment">// Establish the necessary mocks</span>
<span class="hl-variable">$mockBillingManager</span> = <span class="hl-type">Mockery</span>::<span class="hl-property">mock</span>(<span class="hl-value">'Acme\Billing\StripeBillingManager'</span>);

<span class="hl-comment">// Make sure to set the expectations of the mock object before binding it to the IoC</span>
<span class="hl-variable">$I</span>-&gt;<span class="hl-property">getApplication</span>()-&gt;<span class="hl-property">bind</span>(<span class="hl-value">'Acme\Billing\StripeBillingManager'</span>, <span class="hl-variable">$mockBillingManager</span>);

<span class="hl-variable">$I</span>-&gt;<span class="hl-property">amOnRoute</span>(<span class="hl-value">'billing.upgrade.form'</span>);

<span class="hl-variable">$I</span>-&gt;<span class="hl-property">submitForm</span>(<span class="hl-value">'subscription-form'</span>, [
    <span class="hl-value">'plan'</span> =&gt; <span class="hl-value">'premium'</span>,
    <span class="hl-value">'token'</span> =&gt; <span class="hl-property">csrf_token</span>()
]);

<span class="hl-variable">$I</span>-&gt;<span class="hl-property">seeInDatabase</span>(<span class="hl-value">'users'</span>, [<span class="hl-value">'email'</span> =&gt; <span class="hl-value">'testuser@example.com'</span>, <span class="hl-value">'plan'</span> =&gt; <span class="hl-value">'premium'</span>);
</pre>
<p>When the <code>amOnRoute()</code> method is executed, the Application is refreshed and all of your custom bindings are lost in favor of the bindings you establish in your service provider(s). This is triggered by the <code>doRequest()</code> method on the <code>Codeception\Lib\Connector\Laravel4</code> class, which is used by default in the Laravel4 module. The solution that worked for me was to extend the Laravel4 module and its connector class. This allowed me to remove the offending line from the <code>doRequest()</code> method. Also, the Laravel4 module does not provide any methods for helping with temporary binding; creating a custom module allowed me to add some convenient methods to help with this.</p>
<p>Jordan Eldredge has a <a href="https://jordaneldredge.com/blog/writing-a-custom-codeception-module/">great article</a> about writing custom Codeception modules. Using the methods he describes in his post we can create a custom Codeception Module and a new Connector library which is identical to the existing Laravel4 connector library. Only one change is required to the existing connector library, on line 47:</p>
<pre data-lang="php" class="notranslate"><span class="hl-comment">// New class based on Codeception\Lib\Connector\Laravel4</span>

<span class="hl-keyword">class</span> <span class="hl-type">CustomLaravel4Connector</span> {

    <span class="hl-comment">// Most everything remains the same...</span>

    <span class="hl-comment">/**
     * <span class="hl-value">@param</span> <span class="hl-type">Request</span> <span class="hl-variable">$request</span>
     * <span class="hl-value">@return</span> <span class="hl-type">Response</span>
     */</span>
    <span class="hl-keyword">protected</span> <span class="hl-keyword">function</span> <span class="hl-property">doRequest</span>(<span class="hl-injection">$request</span>)
    {
        <span class="hl-comment">//$this-&gt;initialize();  -- Remove this line</span>

        <span class="hl-keyword">return</span> <span class="hl-variable">$this</span>-&gt;<span class="hl-property">kernel</span>-&gt;<span class="hl-property">handle</span>(<span class="hl-variable">$request</span>);
    }

    <span class="hl-comment">//  Don't change anything else</span>

}
</pre>
<p>Now we can create a custom module that extends the Laravel4 module and add some new functionality:</p>
<pre data-lang="php" class="notranslate"><span class="hl-keyword">namespace</span> <span class="hl-type">Codeception\Module</span>;

<span class="hl-keyword">use</span> <span class="hl-type">CustomLaravel4Connector</span>;

<span class="hl-keyword">class</span> <span class="hl-type">CustomLaravel4</span> <span class="hl-keyword">extends</span> \Codeception\Module\Laravel4
{
    <span class="hl-comment">/**
     * Initialize hook.
     */</span>
    <span class="hl-keyword">public</span> <span class="hl-keyword">function</span> <span class="hl-property">_initialize</span>()
    {
        <span class="hl-variable">$this</span>-&gt;<span class="hl-property">checkStartFileExists</span>();
        <span class="hl-variable">$this</span>-&gt;<span class="hl-property">registerAutoloaders</span>();
        <span class="hl-variable">$this</span>-&gt;<span class="hl-property">revertErrorHandler</span>();
        <span class="hl-variable">$this</span>-&gt;<span class="hl-property">client</span> = <span class="hl-keyword">new</span> <span class="hl-type">CustomLaravel4Connector</span>(<span class="hl-variable">$this</span>);
    }

    <span class="hl-comment">/**
     * Allow the Codeception Actor to add a binding to the Laravel IOC
     *
     * <span class="hl-value">@return</span> <span class="hl-type">\Illuminate\Foundation\Application</span>
     */</span>
    <span class="hl-keyword">public</span> <span class="hl-keyword">function</span> <span class="hl-property">bindService</span>(<span class="hl-injection">$abstract, $instance, $shared = <span class="hl-keyword">false</span></span>)
    {
        <span class="hl-variable">$this</span>-&gt;<span class="hl-property">app</span>-&gt;<span class="hl-property">bind</span>(<span class="hl-variable">$abstract</span>, <span class="hl-variable">$instance</span>, <span class="hl-variable">$shared</span> = <span class="hl-keyword">false</span>);
    }

    <span class="hl-comment">/**
     * Allow the Codeception Actor to bind an instantiated object to the Laravel IOC
     *
     * <span class="hl-value">@return</span> <span class="hl-type">\Illuminate\Foundation\Application</span>
     */</span>
    <span class="hl-keyword">public</span> <span class="hl-keyword">function</span> <span class="hl-property">bindInstance</span>(<span class="hl-injection">$abstract, $instance</span>)
    {
        <span class="hl-variable">$this</span>-&gt;<span class="hl-property">app</span>-&gt;<span class="hl-property">instance</span>(<span class="hl-variable">$abstract</span>, <span class="hl-variable">$instance</span>);
    }
}
</pre>
<p>Presto! That is all there is to it. Now your mock objects can be bound appropriately and will remain in place for the duration of the test. Our new acceptance test looks like this:</p>
<pre data-lang="php" class="notranslate"><span class="hl-variable">$I</span> = <span class="hl-keyword">new</span> <span class="hl-type">FunctionalTester</span>(<span class="hl-variable">$scenario</span>);

<span class="hl-variable">$I</span>-&gt;<span class="hl-property">wantTo</span>(<span class="hl-value">'upgrade a subscription plan'</span>);

<span class="hl-variable">$I</span>-&gt;<span class="hl-property">amActingAs</span>(<span class="hl-value">'testuser@example.com'</span>); <span class="hl-comment">// This is a custom helper method which sets the active user</span>

<span class="hl-comment">// Establish the necessary mocks</span>
<span class="hl-variable">$I</span>-&gt;<span class="hl-property">bindService</span>(<span class="hl-value">'Acme\Billing\BillingInterface'</span>, <span class="hl-keyword">function</span>(){
    <span class="hl-keyword">return</span> <span class="hl-type">Mockery</span>::<span class="hl-property">mock</span>(<span class="hl-value">'Acme\Billing\StripeBillingManager'</span>);
});

<span class="hl-variable">$I</span>-&gt;<span class="hl-property">amOnRoute</span>(<span class="hl-value">'billing.upgrade.form'</span>);

<span class="hl-variable">$I</span>-&gt;<span class="hl-property">submitForm</span>(<span class="hl-value">'subscription-form'</span>, [
    <span class="hl-value">'plan'</span> =&gt; <span class="hl-value">'premium'</span>,
    <span class="hl-value">'token'</span> =&gt; <span class="hl-property">csrf_token</span>()
]);

<span class="hl-variable">$I</span>-&gt;<span class="hl-property">seeInDatabase</span>(<span class="hl-value">'users'</span>, [<span class="hl-value">'email'</span> =&gt; <span class="hl-value">'testuser@example.com'</span>, <span class="hl-value">'plan'</span> =&gt; <span class="hl-value">'premium'</span>);
</pre>
<p>I have added my custom module and connector to my <a href="https://github.com/stagerightlabs/laravel-testing-utilities">Laravel-Testing-Utilities</a> package if you would like to make use of them in your own Laravel 4.2 application. Currently they are only on the 1.* branch, but if needed I will add them to the other versions of that package down the road.</p>
]]>
    </content>
    <link rel="alternate" href="https://stagerightlabs.com/blog/using-mockery-with-codeception-and-laravel-4" />
  </entry>
    <entry>
    <title>
      <![CDATA[Using Lumen and Mandrill to Process Incoming Mail]]>
    </title>
    <id>tag:stagerightlabs.com,2015-05-03T00:00:00+0000:1430611200</id>
    <updated>2015-05-03T00:00:00+00:00</updated>
    <summary>
      <![CDATA[Have you ever wanted to automate data entry via email? We can use Laravel Lumen and Mandrill to set up a very simple service for parsing incoming mail and saving important data.]]>
    </summary>
    <content type="html">
      <![CDATA[<p>One of my clients has a WordPress site which makes use of several different contact forms. Powered by the <a href="https://wordpress.org/plugins/contact-form-7/">Contact Form 7</a> plugin, they send their data to an email address when the user submits the form. Recently my client decided that they wanted to send a &quot;Thank you&quot; email as a response to each person who filled out a particular form, and they asked me to set that up for them. I have been using Mandrill for some of my larger applications, and it seemed to me that by combining the Mandrill Incoming Mail API with Lumen, the micro-framework from Laravel, setting up a micro-service to solve this problem would be very easy. Here is how I did it:</p>
<p>First we should create a subdomain on the client's main site, specifically for this project: <code>inbox.clientdomain.com</code>. This is where we will set up our Lumen Application. Next we need to point the MX records for that subdomain to Mandrill. Within your Mandrill dashboard, go to the &quot;Inbound&quot; section and add your new domain to the domain list there. Once that is done Mandrill will provide you with the necessary MX details, and you can also verify that you MX records have been set appropriately. Next, click on the &quot;routes&quot; button for your new domain. When email is received at <code>inbox.clientdomain.com</code> we can assign the URL we want Mandrill to send it to. For this project I set up all mail received at <code>&quot;contact@inbox.clientdomain.com&quot;</code> to be sent to the URL <code>&quot;http://inbox.clientdomain.com/contact&quot;</code>. We could set up other email addresses on that domain to be sent to other places, but this is all we will need for now.</p>
<p>Here is the basic structure of what our micro-service will do:</p>
<ul>
<li>Receive the POST data from Mandrill containing the email message content</li>
<li>Parse out the Sender's email address and Name (if it was provided);</li>
<li>Save a copy of the message to a MySQL database, for archival purposes</li>
<li>Send a &quot;Thank you&quot; email to the sender of the original message</li>
<li>Send a notification to the client that a new message has been received.</li>
</ul>
<p>First we need to install <a href="http://lumen.laravel.com">Lumen</a>:</p>
<pre data-lang="txt" class="notranslate">$ composer create-project laravel/lumen inbox --prefer-dist
</pre>
<p>This will install Lumen to the &quot;inbox&quot; folder in my projects directory. We are going to be using Facades and Eloquent in this project, and personally I prefer using the <code>phpdotenv</code> config files, so we need to uncomment those lines in <code>/bootstrap/app.php</code> to enable those features:</p>
<pre data-lang="php" class="notranslate"><span class="hl-comment">// bootstrap/app.php</span>
<span class="hl-type">Dotenv</span>::<span class="hl-property">load</span>(<span class="hl-property">__DIR__</span>.<span class="hl-value">'/../'</span>);

<span class="hl-comment">// ...</span>

<span class="hl-variable">$app</span>-&gt;<span class="hl-property">withFacades</span>();

<span class="hl-variable">$app</span>-&gt;<span class="hl-property">withEloquent</span>();
</pre>
<p>Now we need to pull in two additional packages via composer: <code>illuminate/mail</code> and <code>guzzlehttp/guzzle</code>:</p>
<pre data-lang="txt" class="notranslate">$ composer require illuminate/mail
$ composer require guzzlehttp/guzzle
</pre>
<p>Lumen does not come with email functionality out of the box, so we are pulling that in here. Also, we need Guzzle to make use of the Mandrill API. Add a config file called <code>/config/services.php</code> like so:</p>
<pre data-lang="php" class="notranslate"><span class="hl-comment">// config/services.php</span>
<span class="hl-keyword">return</span> <span class="hl-property">array</span>(
    <span class="hl-value">'mandrill'</span> =&gt; [
        <span class="hl-value">'secret'</span> =&gt; <span class="hl-property">env</span>(<span class="hl-value">'MANDRILL_API_KEY'</span>),
    ],
);
</pre>
<p>Find the <code>.env.example</code> file in your project's root folder and save it as &quot;<code>.env</code>&quot;. This is where we will keep our environmental configuration values. Add a line for your Mandrill API key:</p>
<pre data-lang="txt" class="notranslate">MANDRILL_API_KEY=XXXXXXXXXXXXXX
</pre>
<p>You should add 32 character random App key while you are here, as well as making sure that your DB credentials are accurate.</p>
<p>If you want to store copies of your messages in your database, you should create a migration and set up that database now:</p>
<pre data-lang="php" class="notranslate"><span class="hl-keyword">class</span> <span class="hl-type">CreateMessagesTable</span> <span class="hl-keyword">extends</span> <span class="hl-type">Migration</span>
{

    <span class="hl-comment">/**
     * Run the migrations.
     *
     * <span class="hl-value">@return</span> <span class="hl-type">void</span>
     */</span>
    <span class="hl-keyword">public</span> <span class="hl-keyword">function</span> <span class="hl-property">up</span>()
    {
        <span class="hl-type">Schema</span>::<span class="hl-property">create</span>(<span class="hl-value">'messages'</span>, <span class="hl-keyword">function</span> (<span class="hl-injection"><span class="hl-type">Blueprint</span> $table</span>) {
            <span class="hl-variable">$table</span>-&gt;<span class="hl-property">increments</span>(<span class="hl-value">'id'</span>);
            <span class="hl-variable">$table</span>-&gt;<span class="hl-property">string</span>(<span class="hl-value">'email'</span>);
            <span class="hl-variable">$table</span>-&gt;<span class="hl-property">string</span>(<span class="hl-value">'name'</span>);
            <span class="hl-variable">$table</span>-&gt;<span class="hl-property">text</span>(<span class="hl-value">'message'</span>);
            <span class="hl-variable">$table</span>-&gt;<span class="hl-property">timestamps</span>();
        });
    }

    <span class="hl-comment">/**
     * Reverse the migrations.
     *
     * <span class="hl-value">@return</span> <span class="hl-type">void</span>
     */</span>
    <span class="hl-keyword">public</span> <span class="hl-keyword">function</span> <span class="hl-property">down</span>()
    {
        <span class="hl-type">Schema</span>::<span class="hl-property">drop</span>(<span class="hl-value">'messages'</span>);
    }
}
</pre>
<p>Now we are ready to set up our routing. In the file <code>app/Http/routes.php</code>, add these route:</p>
<pre data-lang="php" class="notranslate"><span class="hl-comment">// app/Http/routes.php</span>
<span class="hl-variable">$app</span>-&gt;<span class="hl-property">post</span>(<span class="hl-value">'/contact'</span>, [
    <span class="hl-value">'uses'</span> =&gt; <span class="hl-value">'App\Http\Controllers\ContactController@newMessage'</span>
]);

<span class="hl-variable">$app</span>-&gt;<span class="hl-property">get</span>(<span class="hl-value">'/'</span>, <span class="hl-keyword">function</span> (<span class="hl-injection">) </span><span class="hl-keyword">use</span> (<span class="hl-variable">$app</span>) {
    <span class="hl-keyword">return</span> <span class="hl-property">response</span>()-&gt;<span class="hl-property">json</span>([<span class="hl-value">'ok'</span>], 200);
});
</pre>
<p>The first route received the Mandrill Post data and sends it to the <code>newMessage</code> method on our soon to be created ContactController. The second route is just a convenient way to ping the service and make sure it is running.</p>
<p>If this were a larger application, I would next suggest thinking about abstracting our code into a library for handling Mandrill Post Data, and then injecting that library into our ContactController. However, this is such a small service that I don't think we need to really worry about that. True, if we find that we want to handle multiple endpoints with this code, we will gain a lot by abstracting this code into a library that can be used wherever we need it (in keeping with the DRY spirit.) However, we are only concerned with one endpoint for now, so I am going to keep all of the logic within the <code>newMessage</code> controller method.</p>
<p>Create a file called <code>App/Http/Controllers/ContactController.php</code> with a method called <code>newMessage</code>:</p>
<pre data-lang="php" class="notranslate"><span class="hl-comment">// app/Http/Controllers/ContactController.php</span>
<span class="hl-comment">/**
* Handle a Mandrill Inbound API message
*
* <span class="hl-value">@param</span> <span class="hl-type">Request</span> <span class="hl-variable">$request</span>
* <span class="hl-value">@return</span> <span class="hl-type">Response</span>
*/</span>
<span class="hl-keyword">public</span> <span class="hl-keyword">function</span> <span class="hl-property">newMessage</span>(<span class="hl-injection"><span class="hl-type">Request</span> $request</span>)
{
    <span class="hl-comment">// Gather the POST data from Mandrill - if nothing is there, we can call it quits</span>
    <span class="hl-variable">$mandrillEvents</span> = <span class="hl-variable">$request</span>-&gt;<span class="hl-property">input</span>(<span class="hl-value">'mandrill_events'</span>, <span class="hl-keyword">null</span>);
    <span class="hl-keyword">if</span> (!<span class="hl-variable">$mandrillEvents</span>) {
        <span class="hl-keyword">return</span> <span class="hl-property">response</span>()-&gt;<span class="hl-property">json</span>([<span class="hl-value">'ok'</span>], 200);
    }

    <span class="hl-comment">// Decode the WebHook data and get the text content of the email</span>
    <span class="hl-variable">$mail</span> = <span class="hl-property">json_decode</span>(<span class="hl-variable">$mandrillEvents</span>);
    <span class="hl-variable">$body</span> = <span class="hl-variable">$mail</span>[0]-&gt;<span class="hl-property">msg</span>-&gt;<span class="hl-property">text</span>;

    <span class="hl-comment">// Extract the sender's email and the story from the body of the email</span>
    <span class="hl-variable">$senderEmail</span> = <span class="hl-variable">$this</span>-&gt;<span class="hl-property">parseSenderEmail</span>(<span class="hl-variable">$body</span>);
    <span class="hl-variable">$senderName</span> = <span class="hl-variable">$this</span>-&gt;<span class="hl-property">parseSenderName</span>(<span class="hl-variable">$body</span>);

    <span class="hl-comment">//Write the story to the DB</span>
    <span class="hl-type">DB</span>::<span class="hl-property">table</span>(<span class="hl-value">'messages'</span>)-&gt;<span class="hl-property">insert</span>([
        <span class="hl-value">'email'</span> =&gt; <span class="hl-variable">$senderEmail</span>,
        <span class="hl-value">'name'</span> =&gt; <span class="hl-variable">$senderName</span>,
        <span class="hl-value">'message'</span> =&gt; <span class="hl-variable">$body</span>,
    ]);

    <span class="hl-comment">//Send a confirmation email to the submitter</span>
    <span class="hl-variable">$this</span>-&gt;<span class="hl-property">acknowledge</span>(<span class="hl-variable">$senderName</span>, <span class="hl-variable">$senderEmail</span>);

    <span class="hl-comment">// Send a notification that a story was received</span>
    <span class="hl-keyword">return</span> <span class="hl-variable">$this</span>-&gt;<span class="hl-property">notify</span>(<span class="hl-variable">$body</span>, <span class="hl-variable">$senderName</span>);
}
</pre>
<p>First we gather the <code>mandrill_events</code> Post data from the http request. Note that Lumen does not provide an &quot;Input::&quot; facade, we need to get our input directly from the <code>$request</code> object. Per the <a href="https://mandrill.zendesk.com/hc/en-us/articles/205583207-What-is-the-format-of-inbound-email-webhooks-">Mandrill Inbound API</a>, this is a json encoded array of data representing the email message. The <code>$mail</code> array represents the decoded message data.</p>
<p>This email is being sent to us via WordPress, so we have quite a bit of control over the format it is being sent to us in. We don't need to concern ourselves with the headers, or the sender's email address (in this case the sender is our WordPress installation.) All we need is the text from the body of the message, which we gather like so: <code>$body = $mail[0]-&gt;msg-&gt;text;</code>. Now we have the text content of the message and we can do whatever we need to with it.</p>
<p>In my case, I have set up the WordPress contact form to include the Sender's name and email address within the body of the message. To extract them, I created two private methods (<code>parseSenderEmail()</code> and <code>parseSenderName()</code>). The implementation of these methods will depend greatly on the format of the message - your specific implementations will be different from mine so I have not shown them here.</p>
<p>Next we write a copy of the message to the database using the <code>DB</code> facade, and then we send two emails: The first is the acknowledgement message sent to the person who contacted us in the first place, and the second is the notification sent to the client. Here are those two methods:</p>
<pre data-lang="php" class="notranslate"><span class="hl-comment">// app/Http/Controllers/ContactController.php</span>
<span class="hl-comment">/**
 * Send an acknowledgement email to the person who contacted us
 *
 * <span class="hl-value">@param</span> <span class="hl-variable">$senderName</span>
 * <span class="hl-value">@param</span> <span class="hl-variable">$senderEmail</span>
 */</span>
<span class="hl-keyword">private</span> <span class="hl-keyword">function</span> <span class="hl-property">acknowledge</span>(<span class="hl-injection">$senderName, $senderEmail</span>)
{
    <span class="hl-keyword">if</span> (<span class="hl-property">filter_var</span>(<span class="hl-variable">$senderEmail</span>, <span class="hl-property">FILTER_VALIDATE_EMAIL</span>)) {
        <span class="hl-type">Mail</span>::<span class="hl-property">send</span>(<span class="hl-value">'emails.thankyou'</span>, [], <span class="hl-keyword">function</span>(<span class="hl-injection">$message) </span><span class="hl-keyword">use</span> (<span class="hl-variable">$senderName</span>, <span class="hl-variable">$senderEmail</span>) {
            <span class="hl-variable">$message</span>-&gt;<span class="hl-property">from</span>(<span class="hl-value">'client@clientdomain.com'</span>, <span class="hl-value">'Client Name'</span>);
            <span class="hl-variable">$message</span>-&gt;<span class="hl-property">subject</span>(<span class="hl-value">'Thank you for contacting us'</span>);
            <span class="hl-variable">$message</span>-&gt;<span class="hl-property">to</span>(<span class="hl-variable">$senderEmail</span>, <span class="hl-variable">$senderName</span>);
        });
    }
}

 <span class="hl-comment">/**
 * Send a notification to 'contact<span class="hl-value">@example</span>.com`
 * <span class="hl-value">@param</span> <span class="hl-variable">$body</span>
 * <span class="hl-value">@return</span>
 <span class="hl-type"></span>*/</span>
<span class="hl-keyword">private</span> <span class="hl-keyword">function</span> <span class="hl-property">notify</span>(<span class="hl-injection">$body, $senderName</span>)
{
    <span class="hl-type">Mail</span>::<span class="hl-property">send</span>(<span class="hl-value">'emails.notify'</span>, [<span class="hl-value">'body'</span> =&gt; <span class="hl-property">nl2br</span>(<span class="hl-variable">$body</span>)], <span class="hl-keyword">function</span>(<span class="hl-injection">$message) </span><span class="hl-keyword">use</span> (<span class="hl-variable">$senderName</span>) {
        <span class="hl-variable">$message</span>-&gt;<span class="hl-property">from</span>(<span class="hl-value">'client@clientdomain.com'</span>, <span class="hl-value">'Client Name'</span>);
        <span class="hl-variable">$message</span>-&gt;<span class="hl-property">subject</span>(<span class="hl-value">'A New Contact Request from  '</span> . <span class="hl-variable">$senderName</span>);
        <span class="hl-variable">$message</span>-&gt;<span class="hl-property">to</span>(<span class="hl-value">'client@clientdomain.com'</span>, <span class="hl-value">'Client Name'</span>);
    });

    <span class="hl-keyword">return</span> <span class="hl-property">response</span>()-&gt;<span class="hl-property">json</span>([<span class="hl-value">'ok'</span>], 200);
}
</pre>
<p>In the <code>acknowledge()</code> method we are first making sure that the email address we were provided with is valid. If it is, we send an email address to that address with some boilerplate text, which comes from the <code>/resources/views/emails/thankyou.blade.php</code> file.</p>
<p>In the second method, we are essentially forwarding the content of the message to the client directly. We pass the <code>$body</code> content to a blade file called <code>/resources/views/emails/notify.blade.php</code>, which looks like this:</p>
<pre data-lang="html" class="notranslate">&lt;!DOCTYPE html&gt;
&lt;<span class="hl-keyword">html</span> <span class="hl-property">lang</span>=&quot;en-US&quot;&gt;
    &lt;<span class="hl-keyword">head</span>&gt;
        &lt;<span class="hl-keyword">meta</span> <span class="hl-property">charset</span>=&quot;utf-8&quot; /&gt;
    &lt;/<span class="hl-keyword">head</span>&gt;
    &lt;<span class="hl-keyword">body</span>&gt;
        {!! $body !!}
    &lt;/<span class="hl-keyword">body</span>&gt;
&lt;/<span class="hl-keyword">html</span>&gt;
</pre>
<p>Note the use of <code>nl2br()</code> to keep the basic formatting in place. We read the text version of the message, which uses newline characters that will be lost when we show the text in html. Using <code>nl2br()</code> to convert the newlines to &quot;&lt;br /&gt;&quot; tags maintains the basic message format that we are expecting.</p>
<p>That is really all there is to it. Deploy the code to the client's server and you should be good to go.</p>
]]>
    </content>
    <link rel="alternate" href="https://stagerightlabs.com/blog/using-lumen-and-mandrill-to-process-incoming-mail" />
  </entry>
    <entry>
    <title>
      <![CDATA[Laravel 5 Package Development: The Service Provider]]>
    </title>
    <id>tag:stagerightlabs.com,2015-02-01T00:00:00+0000:1422748800</id>
    <updated>2015-02-01T00:00:00+00:00</updated>
    <summary>
      <![CDATA[A service provider is a key part of integrating your custom package into a Laravel application. Laravel 5 has more specific requirements for service providers, but it also enables lots of new possibilities for package integration.]]>
    </summary>
    <content type="html">
      <![CDATA[<p>Let's take a look at upgrading a package service provider to work with Laravel 5. The service provider is intended to inform the application of the package's existence and register its assets. Exactly how this is done will vary depending on the needs of the package, but there are several common items which we will discuss here: Configuration, Language Files, Views and Public Assets. John Hout has a <a href="http://woodmarks.nl/laravel-5-loading-package-views-language-files/">great write up</a> about this, which I will be expanding on.</p>
<p>Two important things before we begin. First have to remove this line from our <code>boot()</code> method, because it is no longer needed:</p>
<pre data-lang="php" class="notranslate"><span class="hl-variable">$this</span>-&gt;<span class="hl-property">package</span>(<span class="hl-value">'rydurham/sentinel'</span>);
</pre>
<p>Secondly, Laravel 5 now ships with a <code>vendor:publish</code> command, which greatly simplifies copying files from the vendor/package directory into the main application. Any folders or files added to the <code>$this-&gt;publishes</code> array in the <code>boot()</code> method will be published when you run the <code>vendor:publish</code> command. (Vendor in this case is literally 'vendor', not the vendor name of your package.) As per the documentation, add this to your <code>boot()</code> command:</p>
<pre data-lang="php" class="notranslate"><span class="hl-comment">// ServiceProvider.php</span>
<span class="hl-keyword">public</span> <span class="hl-keyword">function</span> <span class="hl-property">boot</span>()
{
    <span class="hl-comment">// ...</span>

    <span class="hl-variable">$this</span>-&gt;<span class="hl-property">publishes</span>([
        <span class="hl-property">__DIR__</span>.<span class="hl-value">'/path/to/file1.php'</span> =&gt; <span class="hl-property">base_path</span>(<span class="hl-value">'location/in/main/application/file1.php'</span>),
        <span class="hl-property">__DIR__</span>.<span class="hl-value">'/path/to/directory'</span> =&gt; <span class="hl-property">base_path</span>(<span class="hl-value">'location/in/main/application/directory'</span>),
        <span class="hl-comment">// Add as items as you want, pointing to any location.</span>
        <span class="hl-comment">// Works with both files and directories</span>
    ]);

    <span class="hl-comment">// ...</span>
}
</pre>
<ul class="table-of-contents">
<li><a href="#configuration">Configuration</a></li>
<li><a href="#views-and-assets">Views and Assets</a></li>
<li><a href="#language-files">Language Files</a></li>
<li><a href="#controllers--routes">Controllers &amp; Routes</a></li>
<li><a href="#resources">Resources</a></li>
</ul>
<h2><a id="configuration" href="#configuration" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Configuration</h2>
<p>Configuration management in Laravel 5 has been greatly simplified, and there is no longer a need for accessing config options via a namespace. Add your package config file to the <code>$this-&gt;publishes</code> array and publish it to the main application config folder: <code>base_path('config/sentinel.php')</code>. You can name it whatever you want, but I would recommend giving it the same name as your package.</p>
<p>Accessing config values can be done in the same way you are used to:</p>
<pre data-lang="txt" class="notranslate">Config::get('sentinel.allow_usernames')
</pre>
<p>or you can use this new helper function:</p>
<pre data-lang="txt" class="notranslate">config('sentinel.allow_usernames')
</pre>
<p>It is possible that someone using your package may not publish the config file, or they only have a subset of the configurable values in their local version of the config file. In those situations it can be beneficial to selectively merge their config file with the default config file in the package repository. This can be done with the <code>mergeConfigFrom</code> method in the <code>boot</code> function:</p>
<pre data-lang="php" class="notranslate"><span class="hl-comment">// ServiceProvider.php</span>
<span class="hl-keyword">public</span> <span class="hl-keyword">function</span> <span class="hl-property">boot</span>()
{
    <span class="hl-comment">// ...</span>

    <span class="hl-variable">$this</span>-&gt;<span class="hl-property">mergeConfigFrom</span>(<span class="hl-property">__DIR__</span>.<span class="hl-value">'/../config/sentinel.php'</span>, <span class="hl-value">'sentinel'</span>);

    <span class="hl-comment">// ...</span>
}
</pre>
<h2><a id="views-and-assets" href="#views-and-assets" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Views and Assets</h2>
<p>Package views can still be accessed via a namespace. In lieu of the old <code>view:publish</code> command, you should add your views to the <code>publishes</code> array. The <code>loadViewsFrom</code> function allows you to register the view namespace, however you may want to check to see if the views have been published before you create the namespace:</p>
<pre data-lang="php" class="notranslate"><span class="hl-comment">// ServiceProvider.php</span>
<span class="hl-keyword">public</span> <span class="hl-keyword">function</span> <span class="hl-property">boot</span>()
{
    <span class="hl-comment">// ...</span>

    <span class="hl-comment">// Establish Views Namespace</span>
    <span class="hl-keyword">if</span> (<span class="hl-property">is_dir</span>(<span class="hl-property">base_path</span>() . <span class="hl-value">'/resources/views/packages/rydurham/sentinel'</span>)) {
        <span class="hl-comment">// The package views have been published - use those views.</span>
        <span class="hl-variable">$this</span>-&gt;<span class="hl-property">loadViewsFrom</span>(<span class="hl-property">base_path</span>() . <span class="hl-value">'/resources/views/packages/rydurham/sentinel'</span>, <span class="hl-value">'Sentinel'</span>);
    } <span class="hl-keyword">else</span> {
        <span class="hl-comment">// The package views have not been published. Use the defaults.</span>
        <span class="hl-variable">$this</span>-&gt;<span class="hl-property">loadViewsFrom</span>(<span class="hl-property">__DIR___</span> . <span class="hl-value">'/../views/bootstrap'</span>, <span class="hl-value">'sentinel'</span>);
    }

    <span class="hl-comment">// ...</span>
}
</pre>
<p>Assets like javascript files or images should be added to the <code>publishes</code> array and pointed to the public folder.</p>
<h2><a id="language-files" href="#language-files" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Language Files</h2>
<p>Making translation files available to the application is very straightforward, and translation strings can still be accessed with the <code>trans()</code> function using a namespace:</p>
<pre data-lang="php" class="notranslate"><span class="hl-comment">// ServiceProvider.php</span>
<span class="hl-keyword">public</span> <span class="hl-keyword">function</span> <span class="hl-property">boot</span>()
{
    <span class="hl-comment">// ...</span>

    <span class="hl-comment">// Establish Translator Namespace</span>
    <span class="hl-variable">$this</span>-&gt;<span class="hl-property">loadTranslationsFrom</span>(<span class="hl-property">__DIR__</span> . <span class="hl-value">'/../lang'</span>, <span class="hl-value">'Sentinel'</span>);

    <span class="hl-comment">// ...</span>
}
</pre>
<h2><a id="controllers--routes" href="#controllers--routes" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Controllers &amp; Routes</h2>
<p>Some packages might make use of their own controllers and routing. To add routes, just include the routes.php file as such:</p>
<pre data-lang="php" class="notranslate"><span class="hl-comment">// ServiceProvider.php</span>
<span class="hl-keyword">public</span> <span class="hl-keyword">function</span> <span class="hl-property">boot</span>()
{
    <span class="hl-comment">// ...</span>

    <span class="hl-comment">// Add Sentinel Routes</span>
    <span class="hl-keyword">include</span> <span class="hl-property">__DIR__</span> . <span class="hl-value">'/../routes.php'</span>;

    <span class="hl-comment">// ...</span>
}
</pre>
<p>Controllers should be namespaced, and autoloaded via the composer.json file:</p>
<pre data-lang="json" class="notranslate">// composer.json
<span class="hl-keyword">&quot;autoload&quot;</span>: <span class="hl-property">{</span>
    <span class="hl-keyword">&quot;classmap&quot;</span>: <span class="hl-property">[</span>
        <span class="hl-value">&quot;src/seeds&quot;</span>,
        <span class="hl-value">&quot;src/controllers&quot;</span>
    <span class="hl-property">]</span>,
    <span class="hl-keyword">&quot;psr-4&quot;</span>: <span class="hl-property">{</span>
        <span class="hl-keyword">&quot;Sentinel\\&quot;</span>: <span class="hl-value">&quot;src/Sentinel&quot;</span>
    <span class="hl-property">}</span>
<span class="hl-property">}</span>,
</pre>
<h2><a id="resources" href="#resources" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Resources</h2>
<ul>
<li><a href="http://laravel.com/docs/master/packages">Package Development documentation</a></li>
<li><a href="http://woodmarks.nl/laravel-5-loading-package-views-language-files/">Laravel 5 - loading package views / language files</a></li>
</ul>
]]>
    </content>
    <link rel="alternate" href="https://stagerightlabs.com/blog/laravel-5-package-development-the-service-provider" />
  </entry>
    <entry>
    <title>
      <![CDATA[Single Table Inheritance]]>
    </title>
    <id>tag:stagerightlabs.com,2015-01-25T00:00:00+0000:1422144000</id>
    <updated>2015-01-25T00:00:00+00:00</updated>
    <summary>
      <![CDATA[Single Table Inheritance can be a useful tool in certain situations. Let's look at using Single Table Inheritance in a Laravel application and why we might want to do that.]]>
    </summary>
    <content type="html">
      <![CDATA[<p>Single Table Inheritance is the practice of using one database table to track multiple types of resources. When designing web applications, more often than not you will use one database table for each type of resource you are managing: One table for users, one table for posts, one for widgets, etcetera. This isn't strictly true but it is a good rule of thumb, especially if you are using an Active Record ORM such as Eloquent. Single Table Inheritance turns this idea on its head - and while it does have certain advantages, it is not a common practice.</p>
<p>A few years ago I was working for a startup in the healthcare industry - their idea was to provide an easy way for customers to receive updated about their loved ones in extended care through summaries prepared in laymen's english by trained nurses. Clients would place an order and the company would acquire copies of the medical records in question and have staff nurses write summaries that would then be delivered to the client through the website.</p>
<p>The meat of the application was tracking record requests as they progressed through the various stages of preparation - acquisition from the hospitals, summarized by nurses, reviewed by supervisors and then finally released to clients for consumption. As you can imagine, each phase of a record request required different actions be available to the record object. Not only that, but the types of actions available on a record also depended on the role of the user - admins had to do certain things with records, nurses certain other things, and of course the customer also had a different set of actions they could take against a records. Knowing what stage a particular record request was in became very important, as you can imagine.</p>
<p>Initially we decided to tackle this by using a 'status' column on the record table. &quot;New&quot; for new records, &quot;acquired&quot; for records that had been delivered from medical institutions, 'summarized' for records that had been addressed by the staff nurses and 'approved' for records that had been approved for delivery to the customer. (It was a bit more complicated than that, but you get the idea.) This worked well for the most part, however anytime we needed to present options available for the record we wound up with a lot of code like this:</p>
<pre data-lang="html" class="notranslate">&lt;?php <span class="hl-keyword">foreach</span> (<span class="hl-variable">$records</span> <span class="hl-keyword">as</span> <span class="hl-variable">$record</span>) ?&gt;
&lt;<span class="hl-keyword">tr</span>&gt;
    &lt;<span class="hl-keyword">td</span>&gt;&lt;?php <span class="hl-keyword">echo</span> <span class="hl-variable">$record</span>-&gt;<span class="hl-property">referenceId</span>; ?&gt;&lt;/<span class="hl-keyword">td</span>&gt;
    &lt;<span class="hl-keyword">td</span>&gt;
        &lt;?php <span class="hl-keyword">if</span> (<span class="hl-variable">$record</span>-&gt;<span class="hl-property">status</span> == <span class="hl-value">'new'</span>) ?&gt;
        &lt;<span class="hl-keyword">a</span> <span class="hl-property">href</span>=&quot;...&quot;&gt;Cancel&lt;/<span class="hl-keyword">a</span>&gt;
        &lt;<span class="hl-keyword">a</span> <span class="hl-property">href</span>=&quot;...&quot;&gt;Assign to Nurse&lt;/<span class="hl-keyword">a</span>&gt;
        &lt;?php <span class="hl-keyword">endif</span>; ?&gt; &lt;?php <span class="hl-keyword">if</span> (<span class="hl-variable">$record</span>-&gt;<span class="hl-property">status</span> == <span class="hl-value">'acquired'</span>) ?&gt;
        &lt;<span class="hl-keyword">a</span> <span class="hl-property">href</span>=&quot;...&quot;&gt;Prepare Summary&lt;/<span class="hl-keyword">a</span>&gt;
        &lt;<span class="hl-keyword">a</span> <span class="hl-property">href</span>=&quot;...&quot;&gt;View PDFs&lt;/<span class="hl-keyword">a</span>&gt;
        &lt;?php <span class="hl-keyword">endif</span>; ?&gt; &lt;?php <span class="hl-keyword">if</span> (<span class="hl-variable">$record</span>-&gt;<span class="hl-property">status</span> == <span class="hl-value">'summarized'</span>) ?&gt;
        &lt;<span class="hl-keyword">a</span> <span class="hl-property">href</span>=&quot;...&quot;&gt;Review Summary&lt;/<span class="hl-keyword">a</span>&gt;
        &lt;<span class="hl-keyword">a</span> <span class="hl-property">href</span>=&quot;...&quot;&gt;Approve&lt;/<span class="hl-keyword">a</span>&gt;
        &lt;<span class="hl-keyword">a</span> <span class="hl-property">href</span>=&quot;...&quot;&gt;Reject&lt;/<span class="hl-keyword">a</span>&gt;
        &lt;?php <span class="hl-keyword">endif</span>; ?&gt; &lt;?php <span class="hl-keyword">if</span> (<span class="hl-variable">$record</span>-&gt;<span class="hl-property">status</span> == <span class="hl-value">'approved'</span>) ?&gt;
        &lt;<span class="hl-keyword">a</span> <span class="hl-property">href</span>=&quot;...&quot;&gt;View&lt;/<span class="hl-keyword">a</span>&gt;
        &lt;<span class="hl-keyword">a</span> <span class="hl-property">href</span>=&quot;...&quot;&gt;Process Payment&lt;/<span class="hl-keyword">a</span>&gt;
        &lt;?php <span class="hl-keyword">endif</span>; ?&gt;
    &lt;/<span class="hl-keyword">td</span>&gt;
&lt;/<span class="hl-keyword">tr</span>&gt;
&lt;?php <span class="hl-keyword">endforeach</span>; ?&gt;
</pre>
<p>This is a simplification, but the basic idea remains the same: A lot of time and energy is being spent checking the status of the record, and this doesn't even account for user access control. More often than not we had situations where we were doing things like <code>if ($record-&gt;status == 'acquired' &amp;&amp; $currentUser-&gt;inGroup('nurses'))</code> - it worked, but not that well and it was a bit of a mess. As it happens, this is a perfect scenario for the use of STI. What if, instead of checking for each possible type of action on a given record, we could instead ask the record itself what actions are available to it?</p>
<ul class="table-of-contents">
<li><a href="#the-basics">The Basics</a></li>
<li><a href="#single-table-inheritance-in-eloquent">Single Table Inheritance in Eloquent</a></li>
<li><a href="#single-table-inheritance-in-doctrine">Single Table Inheritance in Doctrine</a></li>
<li><a href="#getting-back-to-our-example">Getting back to our example</a></li>
<li><a href="#additional-resources">Additional Resources</a></li>
</ul>
<h2><a id="the-basics" href="#the-basics" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>The Basics</h2>
<p>To implement STI, one column on the table is designated as the &quot;discriminator&quot; column. This column will be used to determine what type of entity should be returned for each row on the table. In our example, the 'status' column is the discriminator column. Properly configured, your ORM should return the appropriate type of object based on the value of that column. We can then set up child classes that have different methods available to them depending on what actions we want to make available to that type of object.</p>
<p>STI is ideal for situations where you are storing objects that are of very similar types - ideally sharing the need for all the other columns in that table. If you are working with STI and finding that you are adding columns just for the sake of certain types of entities, that is a red flag - there is probably a better way to organize your data. In our case, we are looking to return different types of record objects. Imagine however, that you have a table called &quot;vehicles&quot; and you are storing bicycles, cars and airplanes within it. It is likely that you would want a column that stored the maximum lifting weight allowed for each airplane, or the number of crew members needed to operate it - those columns would be of no use to the Bicycle objects. That is a situation where STI probably won't be very helpful.</p>
<h2><a id="single-table-inheritance-in-eloquent" href="#single-table-inheritance-in-eloquent" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Single Table Inheritance in Eloquent</h2>
<p>Eloquent is an implementation of the Active Record pattern, which places heavy emphasis on using one table for each type of resource you are working with. There is no support for STI out of the box, however we can implement it on our own by overwriting a few key methods in the <code>Illuminate\Database\Eloquent\Model</code> class.</p>
<p>One of the most important methods in an Eloquent Model object is the <code>newFromBuilder</code> function. This method is responsible for instantiating the object in question and using the data from the database to populate the object's member data. This function us called any time you make an eloquent call that returns either a single object or a collection of objects. Modifying this function will be our first step - here is our new version:</p>
<pre data-lang="php" class="notranslate"><span class="hl-comment">/**
 * Create a new model instance requested by the builder.
 *
 * <span class="hl-value">@param</span>  <span class="hl-type">array</span> <span class="hl-variable">$attributes</span>
 * <span class="hl-value">@return</span> <span class="hl-type">\Illuminate\Database\Eloquent\Model</span>
 */</span>
<span class="hl-keyword">public</span> <span class="hl-keyword">function</span> <span class="hl-property">newFromBuilder</span>(<span class="hl-injection">$attributes = array()</span>)
{
    <span class="hl-comment">// Create a new instance of the Entity Type Class</span>
    <span class="hl-variable">$m</span> = <span class="hl-variable">$this</span>-&gt;<span class="hl-property">mapData</span>((array)<span class="hl-variable">$attributes</span>)-&gt;<span class="hl-property">newInstance</span>(<span class="hl-property">array</span>(), <span class="hl-keyword">true</span>);

    <span class="hl-comment">// Hydrate the new instance with the table data</span>
    <span class="hl-variable">$m</span>-&gt;<span class="hl-property">setRawAttributes</span>((array)<span class="hl-variable">$attributes</span>, <span class="hl-keyword">true</span>);

    <span class="hl-comment">// Return the assembled object</span>
    <span class="hl-keyword">return</span> <span class="hl-variable">$m</span>;
}
</pre>
<p>Instead of creating a new instance of the model object (via <code>$instance = $this-&gt;newInstance(array(), true);</code>) we are instead passing the attributes through to a new function called <code>mapData</code> which is responsible for resolving the STI entity type and instantiating it, as such:</p>
<pre data-lang="php" class="notranslate"><span class="hl-comment">/**
 * Use the inheritance map to determine the appropriate object type for a given Eloquent object
 *
 * <span class="hl-value">@param</span> <span class="hl-type">array</span> <span class="hl-variable">$attributes</span>
 * <span class="hl-value">@return</span> <span class="hl-type">mixed</span>
 */</span>
<span class="hl-keyword">public</span> <span class="hl-keyword">function</span> <span class="hl-property">mapData</span>(<span class="hl-injection"><span class="hl-type">array</span> $attributes</span>)
{
    <span class="hl-comment">// Determine the type of entity specified by the discriminator column</span>
    <span class="hl-variable">$entityType</span> = <span class="hl-keyword">isset</span>(<span class="hl-variable">$attributes</span>[<span class="hl-variable">$this</span>-&gt;<span class="hl-property">discriminatorColumn</span>]) <span class="hl-operator">?</span> <span class="hl-variable">$attributes</span>[<span class="hl-variable">$this</span>-&gt;<span class="hl-property">discriminatorColumn</span>] : <span class="hl-keyword">null</span>;

    <span class="hl-comment">// Throw an exception if this entity type is not in the inheritance map</span>
    <span class="hl-keyword">if</span> (!<span class="hl-property">array_key_exists</span>(<span class="hl-variable">$entityType</span>, <span class="hl-variable">$this</span>-&gt;<span class="hl-property">inheritanceMap</span>)) {
        <span class="hl-keyword">throw</span> <span class="hl-keyword">new</span> <span class="hl-type">ModelNotFoundException</span>(<span class="hl-variable">$this</span>-&gt;<span class="hl-property">inheritanceMap</span>[<span class="hl-variable">$entityType</span>]);
    }

    <span class="hl-comment">// Get the appropriate class name from the inheritance map</span>
    <span class="hl-variable">$class</span> = <span class="hl-variable">$this</span>-&gt;<span class="hl-property">inheritanceMap</span>[<span class="hl-variable">$entityType</span>];

    <span class="hl-comment">// Return a new instance of the specified class</span>
    <span class="hl-keyword">return</span> <span class="hl-keyword">new</span> <span class="hl-variable">$class</span>;
}
</pre>
<p>Lets step through this function line by line: First we check to make sure that a <code>$this-&gt;discriminatorColumn</code> value exists. If it does, we find the value of that column in the attributes array containing the row data from the database. This is our <code>$entityType</code>.</p>
<p>We are using an <code>$inheritanceMap</code> as an array that maps discriminator values to entity classes. We now need to make sure that the entity class defined by the discriminator column actually exists - if it doesn't then we throw an exception.</p>
<p>After that, we grab the class name for this <code>$entityType</code> from the <code>$inheritanceMap</code> array and return an new instance of that class back to the <code>newFromBuilder</code> function, which then populates the entity with the data from the database.</p>
<p>We now need to configure our Eloquent Model object appropriately:</p>
<pre data-lang="php" class="notranslate"><span class="hl-comment">// app/Epiphyte/Model.php</span>
<span class="hl-keyword">class</span> <span class="hl-type">Widget</span> <span class="hl-keyword">extends</span> <span class="hl-type">Illuminate</span>\Database\Eloquent\Model
{
    <span class="hl-comment">// Eloquent Configuration</span>
    <span class="hl-keyword">protected</span> <span class="hl-property">$guarded</span> = [<span class="hl-value">'id'</span>];
    <span class="hl-keyword">protected</span> <span class="hl-property">$fillable</span> = [<span class="hl-value">'name'</span>, <span class="hl-value">'description'</span>, <span class="hl-value">'status'</span>];

    <span class="hl-comment">// Single Table Inheritance Configuration</span>
    <span class="hl-keyword">use</span> <span class="hl-type">SingleTableInheritanceTrait</span>;
    <span class="hl-keyword">protected</span> <span class="hl-property">$table</span> = <span class="hl-value">'widgets'</span>;
    <span class="hl-keyword">protected</span> <span class="hl-property">$morphClass</span> = <span class="hl-value">'Epiphyte\Widget'</span>;
    <span class="hl-keyword">protected</span> <span class="hl-property">$discriminatorColumn</span> = <span class="hl-value">'status'</span>;
    <span class="hl-keyword">protected</span> <span class="hl-property">$inheritanceMap</span> = [
        <span class="hl-value">'new'</span> =&gt; <span class="hl-value">'Epiphyte\Entities\Widgets\NewWidget'</span>,
        <span class="hl-value">'processed'</span> =&gt; <span class="hl-value">'Epiphyte\Entities\Widgets\ProcessedWidget'</span>
        <span class="hl-value">'complete'</span> =&gt; <span class="hl-value">'Epiphyte\Entities\Widgets\CompleteWidget'</span>
    ];

    <span class="hl-comment">// ...</span>
}
</pre>
<p>This is where we select the discrimination column and set up the inheritance map. Our intention is to have the child entity classes inherit from this Eloquent model. If we don't explicitly set the <code>$table</code> and <code>$morphClass</code> here, the relationships we establish on the base model will not work properly with the child entities.</p>
<p>There are some additional modifications that need to be made to allow Eloquent to play nicely with the new object types - if you want more information about those techniques I recommend you read <a href="http://snooptank.com/single-table-inheritance-with-eloquent-laravel-4/">this article</a> by Pallav Kaushish - he does a great job of explaining the mechanics of the additional changes needed.</p>
<p>If you want to jump in the deep-end and get started with STI in Eloquent right away, I have a package that provides a trait with everything you need. Add the trait to your Eloquent Model objects, along with the additional configuration settings, and you are good to go. More information about that package <a href="http://stagerightlabs.com/projects/eloquent-sti">can be found here</a>.</p>
<h2><a id="single-table-inheritance-in-doctrine" href="#single-table-inheritance-in-doctrine" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Single Table Inheritance in Doctrine</h2>
<p>Those of you are used to working with Data Mappers, such as Doctrine, will find that Single Table Inheritance is not much of a mental leap from what you are used to. The <a href="http://doctrine-orm.readthedocs.org/en/latest/reference/inheritance-mapping.html">Doctrine documentation for Table Inheritance</a> has a lot of great information - it is very easy to get up and running with STI in very little time. It can be as simple as doing something like this, which I have taken directly from the docs:</p>
<pre data-lang="php" class="notranslate"><span class="hl-comment">/**
 * <span class="hl-value">@Entity</span>
 * <span class="hl-value">@InheritanceType</span>(&quot;SINGLE_TABLE&quot;)
 * <span class="hl-value">@DiscriminatorColumn</span>(name=&quot;discr&quot;, type=&quot;string&quot;)
 * <span class="hl-value">@DiscriminatorMap</span>({&quot;person&quot; = &quot;Person&quot;, &quot;employee&quot; = &quot;Employee&quot;})
 */</span>
<span class="hl-keyword">class</span> <span class="hl-type">Person</span>
{
    <span class="hl-comment">// ...</span>
}

<span class="hl-comment">/**
 * <span class="hl-value">@Entity</span>
 */</span>
<span class="hl-keyword">class</span> <span class="hl-type">Employee</span> <span class="hl-keyword">extends</span> <span class="hl-type">Person</span>
{
    <span class="hl-comment">// ...</span>
}
</pre>
<h2><a id="getting-back-to-our-example" href="#getting-back-to-our-example" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Getting back to our example</h2>
<p>We can now create different classes that represent each possible status type for our medical record requests. Now, instead of checking different status levels within our views do display action links, we can instead ask our entity objects to tell us what actions are available to them. Imagine we were to add something like this to our base model:</p>
<pre data-lang="php" class="notranslate"><span class="hl-keyword">public</span> <span class="hl-keyword">function</span> <span class="hl-property">getActions</span>(<span class="hl-injection">$userLevel</span>)
{
    <span class="hl-keyword">return</span> <span class="hl-variable">$this</span>-&gt;<span class="hl-property">actions</span>[<span class="hl-variable">$userLevel</span>];
}
</pre>
<p>and then in our child entities we were to add member arrays that specify the allowable actions for an object with that status?</p>
<pre data-lang="php" class="notranslate"><span class="hl-keyword">class</span> <span class="hl-type">RecordNew</span> <span class="hl-keyword">extends</span> <span class="hl-type">Epiphyte</span>\Record
{
    <span class="hl-comment">// ..</span>

    <span class="hl-keyword">protected</span> <span class="hl-property">$actions</span> = [
        <span class="hl-value">'client'</span> =&gt; [
            [
                <span class="hl-value">'name'</span>    =&gt; <span class="hl-value">'edit'</span>,
                <span class="hl-value">'action'</span>  =&gt; <span class="hl-value">'ClientReportController@edit'</span>,
                <span class="hl-value">'class'</span>   =&gt; <span class="hl-value">'default'</span>
            ],
            [
                <span class="hl-value">'name'</span>    =&gt; <span class="hl-value">'delete'</span>,
                <span class="hl-value">'action'</span>  =&gt; <span class="hl-value">'ClientReportController@delete'</span>,
                <span class="hl-value">'class'</span>   =&gt; <span class="hl-value">'danger'</span>
            ]
        ]
    ];

    <span class="hl-comment">// ..</span>
}
</pre>
<p>We can set up some convenience functions behind the scenes that convert the action array entries into html button links, and then in our views we can convert our old messy code to something like this:</p>
<pre data-lang="html" class="notranslate">&lt;?php <span class="hl-keyword">foreach</span>(<span class="hl-variable">$records</span> <span class="hl-keyword">as</span> <span class="hl-variable">$record</span>) ?&gt;
&lt;<span class="hl-keyword">tr</span>&gt;
    &lt;<span class="hl-keyword">td</span>&gt;&lt;?php <span class="hl-keyword">echo</span> <span class="hl-variable">$record</span>-&gt;<span class="hl-property">referenceNum</span>; ?&gt;&lt;/<span class="hl-keyword">td</span>&gt;
    &lt;<span class="hl-keyword">td</span>&gt;&lt;?php <span class="hl-keyword">echo</span> <span class="hl-variable">$record</span>-&gt;<span class="hl-property">getActions</span>(<span class="hl-value">'client'</span>); ?&gt;&lt;/<span class="hl-keyword">td</span>&gt;
&lt;/<span class="hl-keyword">tr</span>&gt;
&lt;?php <span class="hl-keyword">endforeach</span>; ?&gt;
</pre>
<p>Much more simple, don't you think?</p>
<h2><a id="additional-resources" href="#additional-resources" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Additional Resources</h2>
<ul>
<li><a href="http://snooptank.com/single-table-inheritance-with-eloquent-laravel-4/">Single Table Inheritance with Eloquent (Laravel 4)</a> by Pallav Kaushish - this article was a huge inspiration for me, and a lot of the code I mention here comes from him.</li>
<li><a href="http://www.colorfultyping.com/single-table-inheritance-in-laravel-4/">Single Table Inheritance In Laravel 4</a> by Mark Smith</li>
<li><a href="http://laravel.io/forum/02-17-2014-eloquent-single-table-inheritance">Eloquent Single Table Inheritance</a> by Shawn McCool</li>
<li><a href="http://blog.tatedavies.com/2011/09/13/setting-up-class-table-inheritance-with-doctrine-2-0/">Setting up Class Table Inheritance with Doctrine 2.0</a> by Chris Tate-Davies</li>
</ul>
]]>
    </content>
    <link rel="alternate" href="https://stagerightlabs.com/blog/single-table-inheritance" />
  </entry>
    <entry>
    <title>
      <![CDATA[Running Homestead 2.0 on Windows]]>
    </title>
    <id>tag:stagerightlabs.com,2014-11-17T00:00:00+0000:1416182400</id>
    <updated>2014-11-17T00:00:00+00:00</updated>
    <summary>
      <![CDATA[Homestead version 2 requires more support tooling than version 1, especially on windows.  Let's take a look at setting up Homestead 2.0 on a Windows machine for the first time.]]>
    </summary>
    <content type="html">
      <![CDATA[<p>Using <a href="https://www.vagrantup.com/">Vagrant</a> has opened up a whole new world of possibilities for me, and adding Laravel's <a href="http://laravel.com/docs/4.2/homestead">Homestead</a> into the mix has only made my life easier. Now that Homestead 2.0 has been released, I have been eager to make the upgrade.</p>
<p>Here are two excellent primers on the changes to be found in Homestead 2.0:</p>
<ul>
<li><a href="http://mattstauffer.co/blog/introducing-laravel-homestead-2.0">Matt Stauffer's Homestead post</a></li>
<li><a href="https://laracasts.com/lessons/say-hello-to-laravel-homestead-two">Free Laracasts Video</a></li>
</ul>
<p>The primary reason I enjoyed using Homestead/Vagrant in the past was that I could keep my host machine free of the clutter that comes with developing websites, and I didn't have to worry about installing software in Windows that has primarily been designed to run on linux - what a headache!</p>
<p>However, Homestead 2.0 requires <a href="https://getcomposer.org/">Composer</a> to be running on your host machine before you can use it. To make this upgrade I had to install PHP and Composer locally, which turned out to be slightly more tricky than expected.</p>
<ul class="table-of-contents">
<li><a href="#setting-up-php">Setting up PHP</a></li>
<li><a href="#installing-composer">Installing Composer</a></li>
<li><a href="#setting-up-homestead">Setting up Homestead</a></li>
<li><a href="#day-to-day-workflow">Day to Day Workflow</a></li>
</ul>
<h2><a id="setting-up-php" href="#setting-up-php" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Setting up PHP</h2>
<p>Conveniently it is easy to use PHP on Windows without installing a complete web stack:</p>
<ol>
<li>Download a <a href="http://windows.php.net/download/">Windows release package</a>. (I ended up using <a href="http://windows.php.net/downloads/releases/php-5.6.3-Win32-VC11-x86.zip">this one</a>.)</li>
<li>Extract the contents of that zip file into a folder of your choice. I ended up using <code>C:\php</code>.</li>
<li>Rename the <code>php.ini-development</code> file to <code>php.ini</code>. There are some <a href="http://php.net/manual/en/install.windows.manual.php#install.windows.manual.phpini">recommended edits</a> you should make, but the most important thing to do is <a href="http://www.herongyang.com/PKI/HTTPS-PHP-Configure-PHP-OpenSSL-on-Windows.html">enable the OpenSSL extension</a>.</li>
<li>Add the PHP directory to your path variable. I have found using an <a href="http://eveditor.com/">editor</a> can make this very easy. If you are running a command line terminal (cmd or Git Bash) you will need to restart it before it will pick up the changes you have made.</li>
<li>You should now be able to run <code>php -v</code> and see something like this:</li>
</ol>
<pre data-lang="txt" class="notranslate">PHP 5.6.3 (cli) (built: Nov 12 2014 17:18:08)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2014 Zend Technologies
</pre>
<h2><a id="installing-composer" href="#installing-composer" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Installing Composer</h2>
<p>Composer has a <a href="https://getcomposer.org/Composer-Setup.exe">Windows Installer</a> which is very easy to use. It will ask you to provide the location of your PHP installation directory. After that it will scan your PHP setup for problems and then install the Composer.phar file. If your OpenSLL extension is not enabled you will see an error message. When complete, you should be able to run <code>composer --version</code> and see something like the following:</p>
<pre data-lang="txt" class="notranslate">Composer version 1.0-dev (ffffab37a294f3383c812d0329623f0a4ba45387) 2014-11-05 06:04:18
</pre>
<p>It is important to note that Composer will be installed in your AppData folder: <code>C:\users\{user-name}\AppData\Roaming\Composer</code></p>
<p>At this point you should add Composer's <code>vendor\bin</code> folder to your path as well - this will be necessary to work with Homestead later.</p>
<pre data-lang="txt" class="notranslate">C:\users\{user-name}\AppData\Roaming\Composer\vendor\bin
</pre>
<h2><a id="setting-up-homestead" href="#setting-up-homestead" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Setting up Homestead</h2>
<p>You can now follow the instructions provided in the Homestead documentation for installation. If you haven't already, you need to download the Homestead Vagrant box:</p>
<pre data-lang="txt" class="notranslate">&gt; vagrant box add laravel/homestead
</pre>
<p>After that, run</p>
<pre data-lang="txt" class="notranslate">&gt; composer global require &quot;laravel/homestead=~2.0&quot;
</pre>
<p>This will copy the Homestead repo into your global Composer vendor folder.</p>
<p>Now run <code>homestead init</code>. This will create a <code>.homestead</code> folder in your user directory:</p>
<pre data-lang="txt" class="notranslate">C:\users\{user-name}\.homestead
</pre>
<p>This is where you will find your <code>homestead.yaml</code> file, which you can configure as needed. Make sure you add your SSH Key - this is critically important. When everything is ready you can run <code>homestead up</code> to boot and provision Homestead.</p>
<h2><a id="day-to-day-workflow" href="#day-to-day-workflow" class="heading-permalink" aria-hidden="true" title="Permalink">#</a>Day to Day Workflow</h2>
<p>Out of the box, Homestead has several commands that you will use day-to-day. These are just wrappers around Vagrant commands that you may already be familiar with. The most important ones are:</p>
<ul>
<li>homestead up</li>
<li>homestead halt</li>
<li>homestead ssh</li>
<li>homestead update</li>
</ul>
<p>When you are starting out your day you will need to boot the box by using <code>homestead up</code>. Then you can access the machine by using <code>homestead ssh</code>.</p>
<p>Currently there is no homestead wrapper for the &quot;--provision&quot; option, so if you add a new site to your yaml file and want to re-provision Homestead you will need to run <code>vagrant up --provision</code> from within the homestead installation folder.</p>
<pre data-lang="txt" class="notranslate">C:\users\{user-name}\AppData\Roaming\Composer\vendor\laravel\homestead
</pre>
<p>There you can also find the <code>Vagrantfile</code> if you want to make changes to how the box is provisioned.</p>
<p>As of this writing, I have found that using <code>homestead ssh</code> to log into the homestead machine creates a SSH session which freezes up on me after a few minutes of use. For now I am just using the regular <code>vagrant ssh</code> command, which does not have the same problem.</p>
<p>Happy homesteading!</p>
]]>
    </content>
    <link rel="alternate" href="https://stagerightlabs.com/blog/running-homestead-20-on-windows" />
  </entry>
    <entry>
    <title>
      <![CDATA[Translating Custom Error Message in Laravel Packages]]>
    </title>
    <id>tag:stagerightlabs.com,2014-10-04T00:00:00+0000:1412380800</id>
    <updated>2014-10-04T00:00:00+00:00</updated>
    <summary>
      <![CDATA[Laravel has great localization tools that make it very easy to translate your application into different languages. How can we adapt those tools to translate custom error messages in a custom package?]]>
    </summary>
    <content type="html">
      <![CDATA[<p>Let's say that you are writing a Laravel package that involves data validation with custom error messages. Let's also say that you are interested in allowing your package to be translated into other languages. How would you pass your custom error strings to your validator?</p>
<p>I ran into this issue when working on my Laravel/Sentry 2 bridge package <a href="http://www.ryandurham.com/projects/sentinel/">Sentinel</a>. (It is not related to Cartalyst's Sentinel Package.) This package uses a Validation system inspired by the book <a href="https://leanpub.com/implementinglaravel"><em>Implementing Laravel</em></a> by Chris Fidao, and in several locations makes use of <a href="http://laravel.com/docs/4.2/validation#custom-error-messages">custom error messages</a>.</p>
<p>When I switched to using language strings instead of strait text I wasn't quite sure how to pull the custom error messages from the language files and pass them to the Validator. Here is what I landed on:</p>
<p>First we need to make sure that the Package's namespace is passed to the Translator. Add this line to the Service Provider's boot function:</p>
<pre data-lang="php" class="notranslate"><span class="hl-comment">// Package Service Provider</span>
<span class="hl-keyword">class</span> <span class="hl-type">SentinelServiceProvider</span> <span class="hl-keyword">extends</span> <span class="hl-type">ServiceProvider</span>
{

   <span class="hl-comment">// ...</span>

   <span class="hl-keyword">public</span> <span class="hl-keyword">function</span> <span class="hl-property">boot</span>()
   {
        <span class="hl-comment">// ...</span>

        <span class="hl-comment">// Add the Translator Namespace</span>
        <span class="hl-variable">$this</span>-&gt;<span class="hl-property">app</span>[<span class="hl-value">'translator'</span>]-&gt;<span class="hl-property">addNamespace</span>(<span class="hl-value">'Sentinel'</span>, <span class="hl-property">__DIR__</span>.<span class="hl-value">'/../lang'</span>);
   }

}
</pre>
<p>The <code>addNamespace</code> function informs Laravel's translator class of the location of our language files and allows for the use of the 'Sentinel' namespace when translating language strings. We can now reference the Sentinel Package language strings via the <code>Illuminate\Translation\Translator</code> class:</p>
<pre data-lang="php" class="notranslate"><span class="hl-keyword">echo</span> <span class="hl-type">Lang</span>::<span class="hl-property">get</span>(<span class="hl-value">'Sentinel::users.noaccess'</span>)

<span class="hl-comment">// Result:</span>
<span class="hl-comment">// You are not allowed to do that.</span>
</pre>
<p>We can also use <code>trans()</code>, which is a helper function that aliases <code>Lang::get()</code>.</p>
<pre data-lang="php" class="notranslate"><span class="hl-keyword">echo</span> <span class="hl-property">trans</span>(<span class="hl-value">'Sentinel::users.noaccess'</span>)

<span class="hl-comment">// Result:</span>
<span class="hl-comment">// You are not allowed to do that.</span>
</pre>
<p>Now we need to feed our custom error message strings to the Validator. This may be different for you, depending on how you handle validation, but the basic idea should remain the same.</p>
<pre data-lang="php" class="notranslate"><span class="hl-comment">// src/Sentinel/Service/Validation/AbstractLaravelValidator.php</span>
<span class="hl-keyword">&lt;?php</span>

<span class="hl-keyword">namespace</span> <span class="hl-type">Sentinel\Service\Validation</span>;

<span class="hl-keyword">use</span> <span class="hl-type">Illuminate\Validation\Factory</span>;

<span class="hl-keyword">abstract</span> <span class="hl-keyword">class</span> <span class="hl-type">AbstractLaravelValidator</span> <span class="hl-keyword">implements</span><span class="hl-type"> ValidableInterface
</span>{

    <span class="hl-comment">/**
     * Validator
     *
     * <span class="hl-value">@var</span> \Illuminate\Validation\Factory
     */</span>
    <span class="hl-keyword">protected</span> <span class="hl-property">$validator</span>;

    <span class="hl-comment">/**
     * Custom Validation Messages
     *
     * <span class="hl-value">@var</span> Array
     */</span>
    <span class="hl-keyword">protected</span> <span class="hl-property">$messages</span> = <span class="hl-property">array</span>();

    <span class="hl-keyword">public</span> <span class="hl-keyword">function</span> <span class="hl-property">__construct</span>(<span class="hl-injection"><span class="hl-type">Factory</span> $validator</span>)
    {
        <span class="hl-variable">$this</span>-&gt;<span class="hl-property">validator</span> = <span class="hl-variable">$validator</span>;

        <span class="hl-comment">// Retrieve Custom Validation Messages &amp; Pass them to the validator.</span>
        <span class="hl-variable">$this</span>-&gt;<span class="hl-property">messages</span> = <span class="hl-property">array_dot</span>(<span class="hl-property">trans</span>(<span class="hl-value">'Sentinel::validation.custom'</span>));
    }

    <span class="hl-comment">// ...</span>
}
</pre>
<p>Here we are establishing a <code>$messages</code> class member and loading our custom language strings when the abstract validator class is instantiated. The <a href="https://github.com/rydurham/Sentinel/blob/master/src/lang/en/validation.php#L127-L159">language files</a> use <code>Sentinel::validaton.custom</code> to refer to the array of custom error message strings.</p>
<p>Now all that remains is to pass the messages to the validator when we are attempting to validate data:</p>
<pre data-lang="php" class="notranslate"><span class="hl-comment">// src/Sentinel/Service/Validation/AbstractLaravelValidator.php</span>
<span class="hl-keyword">abstract</span> <span class="hl-keyword">class</span> <span class="hl-type">AbstractLaravelValidator</span>	<span class="hl-keyword">implements</span><span class="hl-type"> ValidableInterface
</span>{

    <span class="hl-comment">// ...</span>

    <span class="hl-comment">/**
     * Validation passes or fails
     *
     * <span class="hl-value">@return</span> <span class="hl-type">boolean</span>
     */</span>
    <span class="hl-keyword">public</span> <span class="hl-keyword">function</span> <span class="hl-property">passes</span>()
    {
        <span class="hl-variable">$validator</span> = <span class="hl-variable">$this</span>-&gt;<span class="hl-property">validator</span>-&gt;<span class="hl-property">make</span>(<span class="hl-variable">$this</span>-&gt;<span class="hl-property">data</span>, <span class="hl-variable">$this</span>-&gt;<span class="hl-property">rules</span>, <span class="hl-variable">$this</span>-&gt;<span class="hl-property">messages</span>);

        <span class="hl-keyword">if</span> (<span class="hl-variable">$validator</span>-&gt;<span class="hl-property">fails</span>() )
        {
            <span class="hl-variable">$this</span>-&gt;<span class="hl-property">errors</span> = <span class="hl-variable">$validator</span>-&gt;<span class="hl-property">messages</span>();
            <span class="hl-keyword">return</span> <span class="hl-keyword">false</span>;
        }

        <span class="hl-keyword">return</span> <span class="hl-keyword">true</span>;
    }
}
</pre>
<p>The validator takes three arguments:</p>
<ol>
<li>An array of data to be validated.</li>
<li>An array of the validation rules for that data.</li>
<li>Optional: An array of custom error messages.</li>
</ol>
<p>The messages array uses the input and names as array keys, and the corresponding value is the desired message text.</p>
<p>Problem solved!</p>
]]>
    </content>
    <link rel="alternate" href="https://stagerightlabs.com/blog/translating-custom-error-message-in-laravel-packages" />
  </entry>
  </feed>
