Ben Ramsey
Web Developer, Author, & Speaker
https://www.gravatar.com/avatar/0c217b9a7dd0aa31ed40bd0f453727e1.png
2018-07-19T23:04:18+00:00
http://benramsey.com/
Ben Ramsey
https://benramsey.com/
ben@benramsey.com
Copyright © 2004–2018 Ben Ramsey. Except where otherwise noted, this
feed is licensed under a Creative Commons Attribution-ShareAlike 4.0
International license. It contains material originally published by Ben
Ramsey at http://benramsey.com under the Creative Commons
Attribution-ShareAlike 4.0 International license.
Jekyll
Announcing PHP TestFest 2017
2017-07-13T18:00:00+00:00
http://benramsey.com/blog/2017/07/phptestfest
Copyright © 2017 Ben Ramsey.
For those who’ve been around the PHP community for a while, you’ll recall the successful PHP TestFest events that began after a discussion at PHP Quebec in 2008. Many user groups and mentors signed on to host and help with events, and a lot of folks became first-time contributors to the PHP proje...
<p><img width="100%" src="https://files.benramsey.com/ws/blog/2017-07-13-phptestfest/banner-1500x630.jpg"></p>
<p>For those who’ve been around the PHP community for a while, you’ll recall the successful PHP TestFest events that began after a <a href="http://news.php.net/php.qa/64083">discussion at PHP Quebec in 2008</a>. Many user groups and mentors signed on to host and help with events, and a lot of folks became first-time contributors to the PHP project, helping improve our code coverage. It ran strong in a <em>global</em> sense from 2008 to 2010. After that, various groups (particularly the Brazilian groups) have continued the tradition.</p>
<p>A few months ago, at php[tek] in Atlanta, I mentioned to <a href="http://www.dragonbe.com/">Michelangelo</a> that I’d love to bring back PHP TestFest. <a href="https://www.sammyk.me/">Sammy</a> had given <a href="https://speakerdeck.com/sammyk/writing-tests-for-php-source-php-tek-2017">an excellent talk on writing PHPT tests</a>, and <a href="https://twitter.com/ellotheth/status/868583446498734084">Gemma tweeted</a> a link to the <a href="https://wiki.php.net/qa/testfest">old PHP TestFest wiki page</a>. From there, things snowballed.</p>
<h3 id="were-bringing-back-php-testfest">We’re bringing back PHP TestFest!</h3>
<p>The PHP TestFest will run for 4 months this year: September through December. This should give groups plenty of time to plan and prepare one or more local events. In early January, we will award prizes; if your organization/company is interested in offering products or services as prizes, let us know (send email to <a href="mailto:sponsors@phptestfest.org">sponsors@phptestfest.org</a>).</p>
<p class="image right clean"><img src="https://files.benramsey.com/ws/blog/2017-07-13-phptestfest/wooble-wave.svg" width="100%" alt="Wooble" /></p>
<p>This time around, I’ve set up a dedicated website at <a href="https://phptestfest.org/">PHPTestFest.org</a> and <a href="https://groups.google.com/a/phpcommunity.org/group/testfest/">Google Group</a> for discussion. We also have the <a href="https://kiwiirc.com/client/irc.freenode.net#phptestfest">#phptestfest channel</a> on Freenode IRC. All are encouraged to contribute to the <a href="https://github.com/phpcommunity/phptestfest.org">website and tools repository</a>. We need technical tutorials, as well as tutorials from veteran TestFest organizers on how to lead successful PHP TestFest events. Additionally, I’ve provided a stub for a console application in the repository, and I’d love to see that evolve into a robust tool for helping people write and contribute PHPT tests.</p>
<p>I’ll be updating the “<a href="https://phptestfest.org/start/">Getting Started</a>” page on the PHP TestFest website soon with this information and more, so keep posted.</p>
<p>Let’s get to work on improving code coverage of the PHP language!</p>
<hr />
<p><em>Special thanks to Sammy for letting us use “Wooble” as a testing mascot.</em></p>
<p><em>This announcement was cross-posted to the <a href="http://news.php.net/php.qa/67968">php-qa</a>, <a href="http://news.php.net/ug.admins/1222">ug-admins</a>, and <a href="https://groups.google.com/a/phpcommunity.org/d/msg/testfest/FqGWMoKSiuc/EjE06bIBBwAJ">phptestfest</a> mailing lists.</em></p>
<p><em><a rel="author" href="http://benramsey.com">Ben Ramsey</a> is a web developer, author, and speaker. He is a software architect at <a href="https://www.shootproof.com">ShootProof</a>, where he builds a platform for professional photographers. He enjoys organizing user groups and contributing to open source software. Ben blogs at <a href="http://benramsey.com">benramsey.com</a> and is <a href="https://twitter.com/ramsey">@ramsey</a> on Twitter.</em></p>
<p><small><em>“Announcing PHP TestFest 2017” was originally published at <a rel='bookmark' href='https://benramsey.com/blog/2017/07/phptestfest/'>benramsey.com</a> and is Copyright © 2017 Ben Ramsey. It is licensed for use under a <a rel='license' type='text/html' href='http://creativecommons.org/licenses/by-sa/4.0/'>Creative Commons Attribution-ShareAlike license</a>.</em></small></p>
Building PHP Projects on AWS CodeBuild
2016-12-02T23:00:00+00:00
http://benramsey.com/blog/2016/12/aws-codebuild-php
Copyright © 2016 Ben Ramsey.
At AWS re:Invent, Amazon announced a new service for building and testing code: AWS CodeBuild. They provide managed environments for Android, Java, Python, Ruby, Golang, and Node.js. While PHP is missing, it is possible to build PHP projects using the service. Follow along to find out how.
<p><img width="100%" src="https://files.benramsey.com/ws/blog/2016-12-02-aws-codebuild-php/banner-1500x630.jpg"></p>
<p>I’ve had a great time at <a href="https://reinvent.awsevents.com/">AWS re:Invent</a> this week, attending sessions and hanging out with some of the <a href="https://www.shootproof.com/">ShootProof</a> team. My favorite part of the week was the “mini con” on containers. I spent Thursday immersed in sessions dedicated to deploying Docker containers on AWS.</p>
<p>Of course, the main hightlight of re:Invent is always the keynotes and the new services and features announcements they make during the keynotes. One of the new services caught my attention, and I decided to give it a try. That service is <a href="https://aws.amazon.com/codebuild/">AWS CodeBuild</a>.</p>
<p>CodeBuild is designed to be used as part of the <a href="https://aws.amazon.com/codepipeline/">AWS CodePipeline</a>, but it may also be used by itself. Additionally, with AWS’s increased focus on their container service (<a href="https://aws.amazon.com/ecs/">ECS</a>), it’s designed to integrate with ECS to use images you’ve stored in AWS, but it may also use images available on <a href="https://hub.docker.com/">Docker Hub</a>.</p>
<p>Out of the box, CodeBuild provides some managed images that you may use to build your projects. These include environments for Android, Java, Python, Ruby, Golang, and Node.js. PHP is missing from this list, but since you’re able to use other images, I decided to see how easy it is to get up and running on CodeBuild with a PHP project. I chose to try out my <a href="https://github.com/ramsey/uuid">ramsey/uuid library</a> for a simple test. Feel free to follow along with me.</p>
<h3 id="getting-started">Getting Started</h3>
<p>From your Amazon console, search for “CodeBuild” from the AWS Services search box, and choose it from the drop down menu that appears.</p>
<figure>
<figcaption>Figure 1. Search for “CodeBuild” from the AWS console</figcaption>
<p><img class="image center shadow" src="https://files.benramsey.com/ws/blog/2016-12-02-aws-codebuild-php/console-codebuild-search.png" width="75%" alt="Search for CodeBuild from the AWS console" /></p>
</figure>
<p>If you’ve not yet begun playing with CodeBuild, you’ll see a page like the one in Figure 2. Click the “Get Started” button to begin.</p>
<figure>
<figcaption>Figure 2. Getting started with CodeBuild</figcaption>
<p><img class="image center shadow" src="https://files.benramsey.com/ws/blog/2016-12-02-aws-codebuild-php/codebuild-getting-started-2.png" width="75%" alt="Getting started with AWS CodeBuild" /></p>
</figure>
<h3 id="configuring-your-project">Configuring Your Project</h3>
<p>Figure 3 shows most of the options available when configuring a project, pre-filled for the ramsey/uuid library. I’ll step through each option to explain what’s going on.</p>
<p>First, provide a project name. Here, I’ve named the project “ramsey-uuid.”</p>
<p>For <em>Source provider</em>, choose GitHub and then click the link provided to connect to GitHub. This will take you through the OAuth dance to grant AWS with access to your GitHub account. Afterwards, the <em>Repository</em> drop-down will be populated with a list of your GitHub repositories. Here, I’ve selected the uuid repository.</p>
<p>Next, you need to tell CodeBuild how to build your project by specifying an image to use. To use an image in Docker Hub, select “Specify a Docker image” for <em>Environment image</em> and choose “Other” for <em>Custom image type</em>. For the <em>Custom image ID</em>, I’m using <code>benramsey/composer-uuid:latest</code> to specify the repository, image name, and image tag. You may place a <a href="http://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html"><em>buildspec.yml</em> file</a> in the root of your repository to specify build commands (similar to a <a href="https://docs.travis-ci.com/user/customizing-the-build"><em>.travis.yml</em> file</a>). Since ramsey/uuid doesn’t have a <em>buildspec.yml</em> file, I’m specifying the <em>Build commands</em> directly.</p>
<aside class="warning"><blockquote><em>
<p>While there is an <a href="https://hub.docker.com/_/composer/">official Composer image on Docker Hub</a>, it is currently based on the <code>php:7-alpine</code> image (see the <a href="https://github.com/composer/docker/blob/be6ecf58913f704399d11a352818b22951832a60/1.2/Dockerfile">Dockerfile</a> for reference). The PHP image using <a href="https://alpinelinux.org/">Alpine Linux</a> will not run on AWS CodeBuild. Until this is resolved, I recommend using <a href="http://robloach.net/">Rob Loach’s</a> <a href="https://hub.docker.com/r/composer/composer/">composer/composer image</a>, which is what I have used as the basis for my <a href="https://hub.docker.com/r/benramsey/composer-uuid/">benramsey/composer-uuid</a> image.</p>
</em></blockquote></aside>
<p>The full build command I’ve specified for ramsey/uuid is:</p>
<figure class="code-highlight-figure"><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row unnumbered"><div class="code-highlight-line">composer install --no-interaction --prefer-dist <span class="se">\</span>
</div></div><div data-line="2" class="code-highlight-row unnumbered"><div class="code-highlight-line"> <span class="o">&&</span> ./vendor/bin/parallel-lint src tests <span class="se">\</span>
</div></div><div data-line="3" class="code-highlight-row unnumbered"><div class="code-highlight-line"> <span class="o">&&</span> ./vendor/bin/phpunit --verbose --no-coverage <span class="se">\</span>
</div></div><div data-line="4" class="code-highlight-row unnumbered"><div class="code-highlight-line"> <span class="o">&&</span> ./vendor/bin/phpcs src tests --standard<span class="o">=</span>psr2 -sp</div></div></pre></div></figure>
<p>Finally, I’m not generating any artifacts for this build, so I selected “No artifacts” for the <em>Artifacts type</em>, and I chose to let it automatically create a service role in my account.</p>
<p>Our project is now configured, so click <em>Continue</em>, review your choices, click <em>Save and Build</em>, then click <em>Start build</em> to run a build.</p>
<figure>
<figcaption>Figure 3. Configure a project (click to enlarge)</figcaption>
<p><a href="https://files.benramsey.com/ws/blog/2016-12-02-aws-codebuild-php/codebuild-configure.png"><img class="image center shadow" src="https://files.benramsey.com/ws/blog/2016-12-02-aws-codebuild-php/codebuild-configure.png" width="75%" alt="Configure a CodeBuild project" /></a></p>
</figure>
<h3 id="building-your-project">Building Your Project</h3>
<p>As your project is building, you’re able to view the progress of each stage of the build, complete with the last 20 lines of the log output, or you may view the complete log in CloudWatch to see any errors or problems that were emitted during the build. If the build passes, you’ll see the word <em>Succeeded</em> in a comforting bold green.</p>
<figure>
<figcaption>Figure 4. Project build progress (click to enlarge)</figcaption>
<p><a href="https://files.benramsey.com/ws/blog/2016-12-02-aws-codebuild-php/codebuild-progress.png"><img class="image center shadow" src="https://files.benramsey.com/ws/blog/2016-12-02-aws-codebuild-php/codebuild-progress.png" width="75%" alt="View the progress of your project build" /></a></p>
</figure>
<h3 id="what-next">What Next?</h3>
<p>My team is looking into CodeBuild as an alternative to running a dedicated Jenkins instance, and as we evaluate it, there are a few things we’re considering:</p>
<ul>
<li>Some of our tests talk to a dev database in a VPC. How do we grant VPC access to a container running in CodeBuild?</li>
<li>In Jenkins, we capture a handful of artifacts, including code coverage reports and generated docblock documentation. With CodeBuild, we might consider copying these artifacts into an S3 bucket configured for website hosting.</li>
<li>What do we do about the other information we currently capture, like JUnit and Clover XML files?</li>
</ul>
<p>Feel free to use ramsey/uuid and my directions here to play with CodeBuild, or use your own project. In the comments, let me know what you think and whether you’ve run into any caveats with your builds. If you come up with any solutions for the things we’re considering, I’d love to hear them.</p>
<p><em><a rel="author" href="http://benramsey.com">Ben Ramsey</a> is a web developer, author, and speaker. He is a software architect at <a href="https://www.shootproof.com">ShootProof</a>, where he builds a platform for professional photographers. He enjoys organizing user groups and contributing to open source software. Ben blogs at <a href="http://benramsey.com">benramsey.com</a> and is <a href="https://twitter.com/ramsey">@ramsey</a> on Twitter.</em></p>
<p><small><em>“Building PHP Projects on AWS CodeBuild” was originally published at <a rel='bookmark' href='https://benramsey.com/blog/2016/12/aws-codebuild-php/'>benramsey.com</a> and is Copyright © 2016 Ben Ramsey. It is licensed for use under a <a rel='license' type='text/html' href='http://creativecommons.org/licenses/by-sa/4.0/'>Creative Commons Attribution-ShareAlike license</a>.</em></small></p>
7 Tips for php[tek]
2016-05-22T00:00:00+00:00
http://benramsey.com/blog/2016/05/phptek-tips
Copyright © 2016 Ben Ramsey.
This week, I’m attending php[tek]. This is my seventh php[tek], and the first I’ve attended not as a speaker. It’s one of my favorite conferences, and I didn’t want to miss its first year in a new city: St. Louis. As we gear up for the eleventh php[tek] conference, I thought I’d list my seven tip...
<p><img width="100%" src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/banner-1500x630.jpg"></p>
<p>This week, I’m attending <a href="https://tek.phparch.com/">php[tek]</a>. This is my seventh php[tek], and the first I’ve attended not as a speaker. It’s one of my favorite conferences, and I didn’t want to miss its first year in a new city: St. Louis. As we gear up for the eleventh php[tek] conference, I thought I’d list my seven tips for getting the most out of your php[tek] experience.</p>
<ol>
<li>
<p><strong>Hang out in the evenings, after the conference sessions.</strong></p>
<p>php[tek] is known for hosting events in the evening, from video games and board games to hackathons. Make sure you you stick around and take part. One of the best features of PHP is its community, and taking part in the events following the day’s conference sessions is a great way to build relationships in this community.</p>
<div class="box alt">
<div class="row 50% uniform">
<div class="8u">
<span class="image fit clean">
<a href="https://www.flickr.com/photos/akrabat/8784385503/"><img src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek03.jpg" /></a>
</span>
</div>
<div class="4u">
<span class="image fit clean">
<a href="https://www.flickr.com/photos/akrabat/4642947292/"><img src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek05.jpg" /></a>
</span>
</div>
</div>
</div>
</li>
<li>
<p><strong>After the conference events, follow folks to the bar.</strong></p>
<p>Do you have to be a drinker? Nope. There’s much more to a bar than drinking. In Chicago (Rosemont), php[tek] had Shoeless Joe’s, a nearby sports bar, where attendees would congregate each evening following the conference activities. In St. Louis, I don’t know what that place will be, but I’m certain there will be one. This is where relationship-building continues. There’s so much that can come from these relationships—friendships, business opportunities, mentors, and more!</p>
<div class="embed rich Twitter"><blockquote class="twitter-tweet"><p lang="en" dir="ltr">I closed down Shoeless Joe’s with <a href="https://twitter.com/cspruck?ref_src=twsrc%5Etfw">@cspruck</a>, <a href="https://twitter.com/ElizabethN?ref_src=twsrc%5Etfw">@ElizabethN</a>, <a href="https://twitter.com/derickr?ref_src=twsrc%5Etfw">@derickr</a>, <a href="https://twitter.com/coderabbi?ref_src=twsrc%5Etfw">@coderabbi</a>, <a href="https://twitter.com/JimLindForPope?ref_src=twsrc%5Etfw">@JimLindForPope</a>, <a href="https://twitter.com/dshafik?ref_src=twsrc%5Etfw">@dshafik</a>, <a href="https://twitter.com/ptahdunbar?ref_src=twsrc%5Etfw">@ptahdunbar</a>, et al. <a href="https://twitter.com/hashtag/phptek?src=hash&ref_src=twsrc%5Etfw">#phptek</a></p>— Ben Ramsey (@ramsey) <a href="https://twitter.com/ramsey/status/469767931820511232?ref_src=twsrc%5Etfw">May 23, 2014</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
</li>
</ol>
<p></div></p>
<ol>
<li>
<p><strong>Take advantage of the “hallway track,” and don’t forget the regular sessions.</strong></p>
<p>There is a high level of value gained by conversing with other conference attendees in the hallways between (and during) sessions at conferences. This “hallway track” has been touted as one of the most important reasons for attending a conference. The hallway allows you to build relationships and gain better understanding and insight into the technologies and tools you use on a daily basis. It’s an invaluable offering of any conference, but don’t forget about the value gained by attending the sessions. A healthy balance of both will help you have an awesome conference experience.</p>
<div class="box alt">
<div class="row 50% uniform">
<div class="4u">
<span class="image fit clean">
<a href="https://www.flickr.com/photos/eliw/19299729782/"><img src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek09.jpg" /></a>
</span>
</div>
<div class="4u">
<span class="image fit clean">
<a href="https://www.flickr.com/photos/blueparabola/5759017486/"><img src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek14.jpg" /></a>
</span>
</div>
<div class="4u">
<span class="image fit clean">
<a href="https://www.flickr.com/photos/benandliz/26982337936/"><img src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek15.jpg" /></a>
</span>
</div>
</div>
</div>
</li>
<li>
<p><strong>Attend the morning keynote sessions.</strong></p>
<p>The morning keynote sessions set the tone for the conference, and <a href="https://tek16.phparch.com/schedule/">this year’s keynotes</a> are no different. While it’s tempting to stay up into the wee hours of the morning—building relationships at the St. Louis version of Shoeless Joe’s—and sleep in to catch up on rest, you’ll miss some of the most important messages of the conference. The keynotes keep you thinking the rest of the day, and they provide conversation fuel for the hallway track and the after-hours community building. So, plan your rest accordingly and don’t miss the keynotes.</p>
<div class="box alt">
<div class="row 50% uniform">
<div class="4u">
<span class="image fit clean">
<a href="https://www.flickr.com/photos/rbowen/2523296126/"><img src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek10.jpg" /></a>
</span>
</div>
<div class="2u">
<span class="image fit clean">
<a href="https://www.flickr.com/photos/sebastian_bergmann/2527709508/"><img src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek12.jpg" /></a>
</span>
</div>
<div class="2u">
<span class="image fit clean">
<a href="https://www.flickr.com/photos/benandliz/27015991995/"><img src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek13.jpg" /></a>
</span>
</div>
<div class="4u">
<span class="image fit clean">
<a href="https://www.flickr.com/photos/preinheimer/2508587135/"><img src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek11.jpg" /></a>
</span>
</div>
</div>
</div>
</li>
<li>
<p><strong>Join the conference IRC backchannel: #phptek on Freenode.</strong></p>
<p>The #phptek channel on Freenode IRC is the conference backchannel. If you’re unfamiliar with IRC or don’t have an IRC program, <a href="http://webchat.freenode.net/?channels=#phptek">use Freenode’s free webchat</a> to join the #phptek channel. The conference backchannel is an essential tool for navigating the conference. Use it to chat with other attendees during sessions to find out what they’re learning and to share what you’re learning. Use it to discuss your dinner plans, and invite others along with you. You may also use it to keep in touch when the conference is over.</p>
<div class="box alt">
<div class="row 50% uniform">
<div class="4u">
<span class="image fit clean">
<a href="https://www.flickr.com/photos/89711680@N00/2511405443/"><img src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek01.jpg" /></a>
</span>
</div>
<div class="4u">
<span class="image fit clean">
<a href="https://www.flickr.com/photos/akrabat/4639332391/"><img src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek04.jpg" /></a>
</span>
</div>
<div class="4u">
<span class="image fit clean">
<a href="https://www.flickr.com/photos/89711680@N00/2511404709/"><img src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek02.jpg" /></a>
</span>
</div>
</div>
</div>
</li>
<li>
<p><strong>Use the official hashtag: #phptek</strong></p>
<p>The conference’s official hashtag is #phptek. Not #tek. Not #tek16. It’s #phptek. Use it when posting on <a href="https://twitter.com/search?f=tweets&q=%23phptek">Twitter</a>. Use it for posts to <a href="https://www.instagram.com/explore/tags/phptek/">Instagram</a>. Search nearby check-ins on <a href="https://www.swarmapp.com/">Swarm</a>. Use it on your photo uploads to <a href="https://www.flickr.com/">Flickr</a>. Wherever you post about your php[tek] experience, use the hashtag #phptek. Using the hashtag helps connect you and your posts to the greater conversation about php[tek].</p>
<div class="box alt">
<div class="row 50% uniform">
<div class="4u">
<span class="image fit clean">
<a href="https://www.flickr.com/photos/derickrethans/3604018693/"><img src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek08.jpg" /></a>
</span>
</div>
<div class="4u">
<span class="image fit clean">
<a href="https://www.flickr.com/photos/derickrethans/3604849316/"><img src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek06.jpg" /></a>
</span>
</div>
<div class="4u">
<span class="image fit clean">
<a href="https://www.flickr.com/photos/akrabat/4639320697/"><img src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek07.jpg" /></a>
</span>
</div>
</div>
</div>
</li>
<li>
<p><strong>Take lots of pictures and upload them to Flickr.</strong></p>
<p>If you don’t have a Flickr account, <a href="https://www.flickr.com/">go get one</a>. Then, take lots of pictures at php[tek] and upload them to Flickr with the hashtag #phptek. I also recommend licensing your photos for use under a <a href="https://creativecommons.org/">Creative Commons</a> license (Flickr can help you with this), but this is not a requirement—it’s just helpful to the community. Here are photos on Flickr from every year of php[tek]:</p>
<ul>
<li><a href="https://www.flickr.com/search/?sort=date-taken-desc&view_all=1&tags=(phptek%20OR%20tek06)&min_taken_date=1145682000&max_taken_date=1146373199">php|tek 2006</a></li>
<li><a href="https://www.flickr.com/search/?sort=date-taken-desc&view_all=1&tags=(phptek%20OR%20tek07)&min_taken_date=1178946000&max_taken_date=1179723599">php|tek 2007</a></li>
<li><a href="https://www.flickr.com/search/?sort=date-taken-desc&view_all=1&tags=(phptek%20OR%20tek08)&min_taken_date=1211173200&max_taken_date=1211864399">php|tek 2008</a></li>
<li><a href="https://www.flickr.com/search/?sort=date-taken-desc&min_taken_date=1242363600&max_taken_date=1243227599&view_all=1&tags=(phptek%20OR%20tek09)">php|tek 2009</a></li>
<li><a href="https://www.flickr.com/search/?sort=date-taken-desc&min_taken_date=1273726800&max_taken_date=1274763599&view_all=1&tags=(phptek%20OR%20tek10%20OR%20tekx)">php|tek 2010</a></li>
<li><a href="https://www.flickr.com/search/?sort=date-taken-desc&view_all=1&tags=(phptek%20OR%20tek11)&min_taken_date=1305954000&max_taken_date=1306904399">php|tek 2011</a></li>
<li><a href="https://www.flickr.com/search/?sort=date-taken-desc&min_taken_date=1337576400&max_taken_date=1338181199&view_all=1&tags=(phptek%20OR%20tek12)">php|tek 2012</a></li>
<li><a href="https://www.flickr.com/search/?sort=date-taken-desc&view_all=1&tags=(phptek%20OR%20tek13)&min_taken_date=1368334800&max_taken_date=1371877199">php[tek] 2013</a></li>
<li><a href="https://www.flickr.com/search/?sort=date-taken-desc&view_all=1&tags=(phptek%20OR%20tek14)&min_taken_date=1400302800&max_taken_date=1400993999">php[tek] 2014</a></li>
<li><a href="https://www.flickr.com/search/?sort=date-taken-desc&view_all=1&tags=(phptek%20OR%20tek15)&min_taken_date=1431838800&max_taken_date=1432443599">php[tek] 2015</a></li>
</ul>
<p>There’s one more search for php[tek] 2016, but it has no photos (as of May 22). It’s up to you to add them!</p>
<ul>
<li><a href="https://www.flickr.com/search/?sort=date-taken-desc&min_taken_date=1463806800&max_taken_date=1464584399&view_all=1&tags=(phptek%20OR%20tek16)">php[tek] 2016</a></li>
</ul>
</li>
</ol>
<p>php[tek] has been a cultural event in the PHP community over the last eleven years, inaugurating many community memes and launching many community projects. Over the years, we’ve started a <a href="https://twitter.com/ramsey/status/818465884">Terry Chay Fuck Counter</a>; <a href="https://twitter.com/ramsey/status/1840517481">hosted PHP internals meetings</a>; started the PHP standards group that morphed into the PHP-FIG; held sessions on <a href="https://twitter.com/ramsey/status/1874399223">community leadership</a> and <a href="https://twitter.com/CaseySoftware/status/14435677111">panels on running user groups</a>; created numerous unseemly, alliterative names for our favorite local sports bar; drank lots of <a href="https://twitter.com/ramsey/status/334540479406415872">root beer</a>; held summits on mentoring, mental health, and open source; experienced <a href="https://twitter.com/ramsey/status/335056094340739074">Ed Finkler’s first presentation</a> on “Open Sourcing Mental Illness;” exposed the <a href="https://twitter.com/ieatkillerbees/status/471469033829986305">PHP Bard</a>; and much, much more.</p>
<p>The last nine years in Chicago have been amazing for php[tek]. I can’t wait to see what St. Louis will bring.</p>
<div class="embed rich Twitter"><blockquote class="twitter-tweet"><p lang="en" dir="ltr">They’ve still not replaced the bat at Shoeless Joe’s. <a href="https://twitter.com/hashtag/phptek?src=hash&ref_src=twsrc%5Etfw">#phptek</a> <a href="https://twitter.com/joshholmes?ref_src=twsrc%5Etfw">@joshholmes</a> <a href="http://t.co/E4TNdXYGDs">pic.twitter.com/E4TNdXYGDs</a></p>— Ben Ramsey (@ramsey) <a href="https://twitter.com/ramsey/status/601266919212240896?ref_src=twsrc%5Etfw">May 21, 2015</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<div class="embed rich Twitter"><blockquote class="twitter-tweet"><p lang="en" dir="ltr">One last root beer beer. Cheers! <a href="https://twitter.com/paleozombie?ref_src=twsrc%5Etfw">@paleozombie</a> <a href="https://twitter.com/ramsey?ref_src=twsrc%5Etfw">@ramsey</a> <a href="https://twitter.com/kevinbruce?ref_src=twsrc%5Etfw">@kevinbruce</a> <a href="https://twitter.com/SandyS1?ref_src=twsrc%5Etfw">@SandyS1</a> <a href="https://twitter.com/EliW?ref_src=twsrc%5Etfw">@EliW</a> @CattyCreations <a href="https://twitter.com/omerida?ref_src=twsrc%5Etfw">@omerida</a> <a href="https://twitter.com/hashtag/phptek?src=hash&ref_src=twsrc%5Etfw">#phptek</a> <a href="http://t.co/2Vy7JD6gJt">pic.twitter.com/2Vy7JD6gJt</a></p>— Beth Tucker Long (@e3BethT) <a href="https://twitter.com/e3BethT/status/601928243768266752?ref_src=twsrc%5Etfw">May 23, 2015</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<div class="embed rich Twitter"><blockquote class="twitter-tweet"><p lang="en" dir="ltr">My biggest take away from <a href="https://twitter.com/hashtag/phptek?src=hash&ref_src=twsrc%5Etfw">#phptek</a> is that, as a community, we are starting to think about each other as people. That’s pretty cool</p>— Jeff Carouth (@jcarouth) <a href="https://twitter.com/jcarouth/status/602286254483451904?ref_src=twsrc%5Etfw">May 24, 2015</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<p><em><a rel="author" href="http://benramsey.com">Ben Ramsey</a> is a web developer, author, and speaker. He is a software architect at <a href="https://www.shootproof.com">ShootProof</a>, where he builds a platform for professional photographers. He enjoys organizing user groups and contributing to open source software. Ben blogs at <a href="http://benramsey.com">benramsey.com</a> and is <a href="https://twitter.com/ramsey">@ramsey</a> on Twitter.</em></p>
<p><small><em>“7 Tips for php[tek]” was originally published at <a rel='bookmark' href='https://benramsey.com/blog/2016/05/phptek-tips/'>benramsey.com</a> and is Copyright © 2016 Ben Ramsey. It is licensed for use under a <a rel='license' type='text/html' href='http://creativecommons.org/licenses/by-sa/4.0/'>Creative Commons Attribution-ShareAlike license</a>.</em></small></p>
Mastering OAuth 2.0 Published
2016-05-15T02:00:00+00:00
http://benramsey.com/blog/2016/05/mastering-oauth2-published
Copyright © 2016 Ben Ramsey.
I've published my first article in _php[architect]_ magazine since 2009! It's only fitting that it's an article on OAuth 2.0, since one of the last articles I published in their magazine was on OAuth 1.0. I'm proud and excited to finally publish a new article with them after such a long hiatus, a...
<p><a href="https://www.phparch.com/magazine/2016-2/may/"><img class="image right no-fit clean" src="https://files.benramsey.com/ws/blog/2016-05-14-mastering-oauth2/cover-232x300.png" alt="php[architect] May 2016" /></a></p>
<p>I’ve published my first article in <a href="https://www.phparch.com/"><em>php[architect]</em> magazine</a> since 2009! It’s only fitting that it’s an article on OAuth 2.0, since one of the last articles I published in their magazine was on OAuth 1.0. I’m proud and excited to finally publish a new article with them after such a long hiatus, and I hope my next article doesn’t take seven years to write.</p>
<blockquote>
<p>OAuth 2.0 is the de facto standard for authenticating users with third-party websites. If you want access to a user’s data in Google or Facebook, for example, OAuth 2.0 is what you use. But, let’s face it: OAuth 2.0 is not easy, and to make matters worse, it seems everyone has a slightly different implementation, making interoperability a nightmare. Fortunately, the PHP League of Extraordinary Packages has released version 1 of the league/oauth2-client library. Aiming for simplicity and ease-of-use, league/oauth2-client provides a common interface for accessing many OAuth 2.0 providers.</p>
</blockquote>
<p>It wasn’t easy for me to write this article. Call it writers’ block, procrastination, or what have you, I kept putting off writing the article over and over. I had more than a few false starts, and I tried a variety of different formats, convinced it was my workflow and process that was hindering me. In the end, I just had to write. I owe <a href="https://twitter.com/omerida">Oscar</a> a few beers at <a href="https://tek.phparch.com">php[tek]</a> for putting him through that.</p>
<h3 id="mistakes-were-made">Mistakes Were Made</h3>
<p>I began writing the article in August of last year. As a result of the long writing process, the Instagram client I registered for use in writing the article was registered before <a href="http://developers.instagram.com/post/133424514006/instagram-platform-update">Instagram deprecated the <code>/users/self/feed</code> endpoint</a> (thanks to an astute reader for pointing this out!). This means there are errors in the published version of the article, and I am truly sorry for this. As a technical author, it’s embarrassing—especially since it’s an error that could have been avoided.</p>
<aside class="info"><blockquote><em>
<p>There is a full, working <a href="https://github.com/ramsey/oauth2-phparch/releases/tag/phparch-may2016">package of code available for download</a> on GitHub. It includes the full application for the code example used in the article, including updated code that uses the correct Instagram endpoint. Download the code and read the <a href="https://github.com/ramsey/oauth2-phparch/blob/phparch-may2016/readme.md">readme.md file</a> to find out how to run it.</p>
</em></blockquote></aside>
<p>Fortunately, there’s an easy fix for this. In <strong>Listing 2</strong> of my article’s example code (app/Http/Controllers/HomeController.php), you’ll find the following lines of code:</p>
<figure class="code-highlight-figure"><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="nv">$feedRequest</span> <span class="o">=</span> <span class="nx">Instagram</span><span class="o">::</span><span class="na">getAuthenticatedRequest</span><span class="p">(</span>
</div></div><div data-line="2" class="code-highlight-row unnumbered"><div class="code-highlight-line"> <span class="s1">'GET'</span><span class="p">,</span>
</div></div><div data-line="3" class="code-highlight-row unnumbered"><div class="code-highlight-line"> <span class="s1">'https://api.instagram.com/v1/users/self/feed'</span><span class="p">,</span>
</div></div><div data-line="4" class="code-highlight-row unnumbered"><div class="code-highlight-line"> <span class="nv">$instagramToken</span>
</div></div><div data-line="5" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="p">);</span></div></div></pre></div></figure>
<p>This code uses the deprecated Instagram endpoint <code>https://api.instagram.com/v1/users/self/feed</code>. There is no replacement for this endpoint, but we can substitute it with another one: <code>https://api.instagram.com/v1/users/self/media/recent</code>. This new endpoint won’t return a user’s Instagram feed, but it will return their most recent uploads, which will suffice for the example application. The updated code should look like this:</p>
<figure class="code-highlight-figure"><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="nv">$feedRequest</span> <span class="o">=</span> <span class="nx">Instagram</span><span class="o">::</span><span class="na">getAuthenticatedRequest</span><span class="p">(</span>
</div></div><div data-line="2" class="code-highlight-row unnumbered"><div class="code-highlight-line"> <span class="s1">'GET'</span><span class="p">,</span>
</div></div><div data-line="3" class="code-highlight-row unnumbered"><div class="code-highlight-line"> <span class="s1">'https://api.instagram.com/v1/users/self/media/recent'</span><span class="p">,</span>
</div></div><div data-line="4" class="code-highlight-row unnumbered"><div class="code-highlight-line"> <span class="nv">$instagramToken</span>
</div></div><div data-line="5" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="p">);</span></div></div></pre></div></figure>
<h3 id="thanks-for-reading">Thanks For Reading</h3>
<p>If you took the time to read the article, thank you so much. If you haven’t yet, <a href="https://www.phparch.com/magazine/2016-2/may/">go grab a copy of the May issue and read it</a>.</p>
<p>Please take a moment to let me know what you think. OAuth can be explained in simple terms, but to grok it, it’s difficult to distill into concise code examples. That was my goal. I’m working the article into a talk, so I’d like to know how I can improve the content and examples.</p>
<p>On Twitter, I posted a thread of tweets where I mention a few things about OAuth and then list many of the <em>php[architect]</em> articles that have covered it. Feel free to read through this conversation and check out the other OAuth articles to increase your own understanding.</p>
<div class="embed rich Twitter"><blockquote class="twitter-tweet"><p lang="en" dir="ltr">While OAuth is used practically everywhere these days, there’s still so much misunderstanding around how it works. <a href="https://twitter.com/hashtag/oauth?src=hash&ref_src=twsrc%5Etfw">#oauth</a> (1/12)</p>— Ben Ramsey (@ramsey) <a href="https://twitter.com/ramsey/status/731215630062485505?ref_src=twsrc%5Etfw">May 13, 2016</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<p>Finally, my friend <a href="https://twitter.com/shrtwhitebldguy">Matt Frost</a> recently wrote <a href="http://phpa.me/oauthbook"><em>Integrating Web Services with OAuth and PHP</em></a>, also published by the good folks at <em>php[architect]</em>. Check it out to learn more about OAuth versions 1 and 2.</p>
<p><em><a rel="author" href="http://benramsey.com">Ben Ramsey</a> is a web developer, author, and speaker. He is a software architect at <a href="https://www.shootproof.com">ShootProof</a>, where he builds a platform for professional photographers. He enjoys organizing user groups and contributing to open source software. Ben blogs at <a href="http://benramsey.com">benramsey.com</a> and is <a href="https://twitter.com/ramsey">@ramsey</a> on Twitter.</em></p>
<p><small><em>“Mastering OAuth 2.0 Published” was originally published at <a rel='bookmark' href='https://benramsey.com/blog/2016/05/mastering-oauth2-published/'>benramsey.com</a> and is Copyright © 2016 Ben Ramsey. It is licensed for use under a <a rel='license' type='text/html' href='http://creativecommons.org/licenses/by-sa/4.0/'>Creative Commons Attribution-ShareAlike license</a>.</em></small></p>
Post-Open Source
2016-04-26T00:00:00+00:00
http://benramsey.com/blog/2016/04/post-open-source
Copyright © 2016 Ben Ramsey.
I’m a tad late to this discussion, but I think it’s still pertinent today—perhaps even more so—and Jordi Boggiano’s recent post, “Common files in PHP packages,” got me thinking about the lack of open source licenses in public repositories.
<p><img width="100%" src="https://files.benramsey.com/ws/blog/2016-04-25-post-open-source/banner-1500x630.jpg"></p>
<p>I’m a tad late to this discussion, but I think it’s still pertinent today—perhaps even more so—and Jordi Boggiano’s recent post, “<a href="https://seld.be/notes/common-files-in-php-packages">Common files in PHP packages</a>,” got me thinking about the lack of open source licenses in public repositories.</p>
<p>In his post, Jordi explains how he analyzed all packages at <a href="https://packagist.org/">Packagist</a>, specifically for the sake of identifying common file names developers are using for their change logs. As part of that analysis, he was also able to tell how many projects have a license file, about which he writes:</p>
<blockquote>
<p>55% [of PHP packages at Packagist] have a LICENSE file, that’s.. pretty disastrous but hopefully a lot of those that don’t at least indicate in the README and composer.json</p>
</blockquote>
<p><span class="pullquote-right " data-pullquote="Why are so few repositories adding open source licenses?"></span>
In a <a href="http://www.softwarefreedom.org/resources/2013/lcs-slides-aaronw/">2013 analysis</a> of software licenses on Github, Aaron Williamson, then Senior Staff Counsel at the Software Freedom Law Center, found that 14.9% of repositories had a top-level license file, while 3.7% only announce the license in the project’s README<sup id="fnref:analysis"><a href="#fn:analysis" class="footnote">1</a></sup>. Of the top licenses, he noted that there has been a significant shift since 2000 in favor of more permissive licenses (MIT, BSD, etc.) and surmises this could be the result of “corporate influence/allergy to GPL” or a reaction against the GPL, favoring “freedom of developer over freedom of users.” Why are so few repositories adding open source licenses?</p>
<p><a href="http://lu.is/blog/2013/01/27/taking-post-open-source-seriously-as-a-statement-about-copyright-law/">Luis Villa posits</a> it might be because developers are rejecting permission culture.</p>
<blockquote>
<p>The open license ecosystem assumes that sharing can’t (or even shouldn’t) happen without explicit permission in the form of licenses. What if “post open source” is an implicit critique of that assumption – saying, in essence, “I reject the permission culture”?</p>
</blockquote>
<p>So, when James Governor posted in September 2012 his sentiment about younger developers being about “post open source software,” it was perhaps a bit of tongue-in-cheek crotchety cane-shaking about a cultural shift in developer attitudes toward open source and the need to grant permission.</p>
<div class="embed rich Twitter"><blockquote class="twitter-tweet"><p lang="en" dir="ltr">younger devs today are about POSS - Post open source software. fuck the license and governance, just commit to github.</p>— Yan Tan Tethera (@monkchips) <a href="https://twitter.com/monkchips/status/247584170967175169?ref_src=twsrc%5Etfw">September 17, 2012</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<p>If we’re in a post-open source era and open source licenses represent permission granted to use one’s code, then is this era marked by a reaction against the need for that permission? After all, the “younger devs” grew up in a post-Napster world full of DRM, EULAs, IP/copyright lobbyists, and legalspeak about what we can and cannot do with the content and software we’ve purchased. Open source licenses are yet another way to proliferate that permission culture. It’s no wonder there’s a backlash against the need for licenses.</p>
<p>In Lawrence Lessig’s 2004 book <em>Free Culture</em>, Lessig warned:</p>
<blockquote>
<p>Free cultures are cultures that leave a great deal open for others to build upon; unfree, or permission, cultures leave much less. Ours was a free culture. It is becoming much less so.</p>
</blockquote>
<p>Are open source licenses just another manifestation of the shift to a permission culture and away from a free culture? While companies have embraced open source software and many contribute back to open source projects under a variety of permissive licenses, I can’t help but feel that open source is losing its soul. These days, I don’t hear people talking about it as a philosophy. Rather, the focus is always on licensing and business cases—the <em>permission</em> to use it.</p>
<p>What do you think? Do open source licenses propagate permission culture? Are we in a post-open source era?</p>
<div class="footnotes">
<ol>
<li id="fn:analysis">
<p>The analysis used <a href="http://www.fossology.org/">FOSSology</a> to examine 1,692,135 Github repositories out of about 6 million. Alternate locations of licenses could not be accounted for (file headers, subdirectories, unexpected file names, etc.). <a href="#fnref:analysis" class="reversefootnote">↩</a></p>
</li>
</ol>
</div>
<p><em><a rel="author" href="http://benramsey.com">Ben Ramsey</a> is a web developer, author, and speaker. He is a software architect at <a href="https://www.shootproof.com">ShootProof</a>, where he builds a platform for professional photographers. He enjoys organizing user groups and contributing to open source software. Ben blogs at <a href="http://benramsey.com">benramsey.com</a> and is <a href="https://twitter.com/ramsey">@ramsey</a> on Twitter.</em></p>
<p><small><em>“Post-Open Source” was originally published at <a rel='bookmark' href='https://benramsey.com/blog/2016/04/post-open-source/'>benramsey.com</a> and is Copyright © 2016 Ben Ramsey. It is licensed for use under a <a rel='license' type='text/html' href='http://creativecommons.org/licenses/by-sa/4.0/'>Creative Commons Attribution-ShareAlike license</a>.</em></small></p>
Introducing ramsey/uuid
2016-04-24T18:00:00+00:00
http://benramsey.com/blog/2016/04/ramsey-uuid
Copyright © 2016 Ben Ramsey.
It seems quite absurd for me to introduce ramsey/uuid, a library that saw its 1.0.0 release on July 19, 2012, and is now at version 3.4.1, having had 35 releases since its first, but what’s even more ludicrous is that I haven’t once blogged about this library. I mention it only in passing in my “...
<p><img width="100%" src="https://files.benramsey.com/ws/blog/2016-04-24-ramsey-uuid/banner-1500x630.jpg"></p>
<p class="lead-in">It seems quite absurd for me to introduce ramsey/uuid, a library that saw its 1.0.0 release on July 19, 2012, and is now at version 3.4.1, having had 35 releases since its first, but what’s even more ludicrous is that I haven’t once blogged about this library. I mention it only in passing in my “<a href="https://benramsey.com/blog/2014/02/dates-are-hard/">Dates Are Hard</a>” post. So, allow me to introduce you to perhaps a familiar face, an old friend, the <a href="https://benramsey.com/projects/ramsey-uuid/">ramsey/uuid library for PHP</a>.</p>
<h3 id="beginnings">Beginnings</h3>
<p>I’ve been asked on more than one occasion why I created ramsey/uuid. Why was it needed? Why did I open source it?</p>
<p>It all began with <a href="https://getcomposer.org/">Composer</a>. In 2012, Composer was taking off, and there was a lot of excitement around creating userland PHP packages and distributing them for others to use. I had contributed a number of times to open source projects, but I had never maintained one of my own. So, it began as an experiment. I wanted to experience what it was like to manage an open source project and accept pull requests, feedback, and bug reports from others.</p>
<p>Once I had resolved to create a package for this little experiment, I needed something to work on that presented a problem I felt others in the PHP community had not yet sufficiently solved. I also looked to other programming language communities to see what problems they had solved that PHP could benefit from.</p>
<p>At some point, I stumbled across the <a href="http://docs.oracle.com/javase/6/docs/api/java/util/UUID.html">Java</a> and <a href="https://docs.python.org/3/library/uuid.html">Python</a> UUID implementations, both of which provide rich interfaces for generating UUIDs. Aside from the <a href="https://pecl.php.net/package/uuid">PECL uuid</a> package and a handful of small libraries generating UUIDs with <code>mt_rand()</code>, I couldn’t find a PHP userland implementation providing functionality similar to that of the Java and Python libraries.</p>
<p>I had found a problem in need of a PHP userland solution! I set to work right away, quickly releasing a 1.0.0 version. Little did I know this marked the beginning of a long road for a small package that would become popular and widely-used.</p>
<h3 id="what-is-a-uuid">What is a UUID?</h3>
<p>UUID is an acronym for <em>universally unique identifier</em>. A UUID is a 128-bit integer with some special formatting rules based on its variant and version. When presented as a string, a UUID looks something like this:</p>
<pre><code>379dae82-5a2b-4c4b-8193-b8e7749a3495
</code></pre>
<p>A UUID aims to be <em>practically unique</em> such that information may be uniquely identified across distributed systems, without central coordination of identifiers. There are 16<sup>32</sup> possible UUIDs, so it’s highly unlikely that there will be a duplicate. <a href="https://en.wikipedia.org/w/index.php?title=Universally_unique_identifier&oldid=716398107">According to Wikipedia</a>, for randomly generated UUIDs, “only after generating 1 billion UUIDs every second for the next 100 years, the probability of creating just one duplicate would be about 50%.”</p>
<p><a href="https://tools.ietf.org/html/rfc4122.html">RFC 4122</a> defines a specific variant of UUIDs having five versions:</p>
<ul>
<li>Version 1 is constructed from the current timestamp and local machine MAC address</li>
<li>Version 2 is the DCE Security version; it is similar to version 1, but RFC 4122 does not explicitly define it, so it is left out of most implementations</li>
<li>Version 3 is constructed from a namespace and an MD5 hash of a name; given the same namespace and name, the UUID generated will always be the same</li>
<li>Version 4 is randomly-generated and is probably the most common version used</li>
<li>Version 5 is the same as version 3, but it uses SHA-1 hashing instead; it is the preferred version for name-based UUIDs</li>
</ul>
<h3 id="whats-in-a-name">What’s In a Name?</h3>
<figure class="quote"><blockquote><p>What’s in a name? That which we call a rose <br />
By any other name would smell as sweet.</p></blockquote><figcaption class="quote-source"><span class="quote-author">Juliet</span> <cite class="quote-title"><em>Romeo and Juliet</em></cite></figcaption></figure>
<p>If you used ramsey/uuid before the 3.x series, you’ll recall that this library began its life with the vendor name <em>Rhumsaa</em>. There were several problems with this name. It was too close to Ramsey, so many people assumed that’s what it was. As a result, in conversation, it was referred to as Ramsey UUID, and folks searching for it would use the search terms “Ramsey UUID.” It became very confusing, and those who knew it was Rhumsaa and not Ramsey didn’t know how to pronounce it.</p>
<p>I received complaints about <a href="https://twitter.com/henrikbjorn/status/302090900052520960">not remembering how to spell it</a>. I heard from others who <a href="https://twitter.com/Hipsterjazzbo/status/592059359833694208">didn’t realize I was the package maintainer</a>. One developer even encountered a problem and assumed it was a result of my “<a href="https://github.com/ramsey/uuid/issues/36">GitHub username change</a>;” they thought I had changed my GitHub username from <em>rhumsaa</em> to <em>ramsey</em>, breaking the location of the package in Packagist.</p>
<p>So, what does <em>rhumsaa</em> mean, after all? As I wrote in my “<a href="https://benramsey.com/blog/2013/08/wild-garlic/">Wild Garlic</a>” post, “[T]he word <em>rhumsaa</em> is a Manx word derived from the Old Norse <em>hrams-á</em>, meaning ‘wild garlic river.’ In English, this word is <em>ramsey</em>.”</p>
<p>I was attempting to be clever with my vendor name, and it caused a lot of confusion.</p>
<p>As we were deep in the middle of development on the 3.x series, I decided a vendor name change from 2.x to 3.x might be a good idea and mitigate a lot of this confusion. I <a href="https://twitter.com/ramsey/statuses/494560272326336512">asked on Twitter</a> and opened <a href="https://github.com/ramsey/uuid/issues/48">Issue #48</a> to solicit feedback from the community for the name change. In the end, I made the decision to change the vendor name to Ramsey. I first updated my other Rhumsaa packages (i.e. <a href="https://github.com/ramsey/twig-codeblock">ramsey/twig-codeblock</a>, <a href="https://github.com/ramsey/vnderror">ramsey/vnderror</a>, etc.) and then I changed the name of ramsey/uuid for the 3.x series.</p>
<p>I tried to make the transition as easy as possible. I’m sure there are better ways to handle changes like this, and in retrospect, I probably should have forked the package to allow projects to use both rhumsaa/uuid and ramsey/uuid together, similar to how <a href="http://mtdowling.com/blog/2014/03/15/guzzle-4-rc/">the Guzzle project addressed a similar namespace and package name change</a>. Nevertheless, I’ve only heard from a handful of those who’ve encountered problems with the upgrade or couldn’t upgrade yet due to other packages using the older 2.x series.</p>
<h3 id="when-uuids-collide">When UUIDs Collide</h3>
<p>Shortly before the GA release of 3.0.0, I received a troublesome bug report. <a href="https://github.com/ramsey/uuid/issues/80">Issue #80</a> purported to show that version 4 UUID collisions were occurring on a regular basis even in small-scale tests, and as I mentioned earlier this should not be probable. After several more corroborating reports, we were faced with a conundrum.</p>
<p>Since I couldn’t reproduce the issue, and no one could produce a sufficient reproducible script, the issue sat around for a long time. Every couple of weeks or so, someone would chime in to ask the status or confirm they had seen collisions. <a href="https://github.com/ramsey/uuid/issues/80#issuecomment-144331529">It began to scare people</a>, and I was worried that community confidence in the library was degrading. I was actually stressed by the whole situation; I wanted my library to be useful and dependable.</p>
<p>Finally, after many months attempting to identify the culprit—I was certain it wasn’t inside the library’s code, since ramsey/uuid relies on external random generators—I had a conversation with <a href="https://twitter.com/willemjanz">Willem-Jan Zijderveld</a> and <a href="https://twitter.com/ircmaxell">Anthony Ferrara</a> in the #phpc channel on <a href="http://freenode.net/">Freenode IRC</a>. Willem-Jan pointed us to the <a href="https://wiki.openssl.org/index.php/Random_fork-safety">OpenSSL random fork-safety</a> issue, where the OpenSSL project explains:</p>
<blockquote>
<p>Since the UNIX fork() system call duplicates the entire process state, a
random number generator which does not take this issue into account will
produce the same sequence of random numbers in both the parent and the child
(or in multiple children), leading to cryptographic disaster (i. e. people
being able to read your communications).</p>
<p>OpenSSL’s default random number generator mixes in the PID, which provides a
certain degree of fork safety. However, once the PIDs wrap, new children will
start to produce the same random sequence as previous children which had the
same PID.</p>
</blockquote>
<p>They go on to say:</p>
<blockquote>
<p>OpenSSL cannot fix the fork-safety problem because it’s not in a position to do so.</p>
</blockquote>
<p>OpenSSL was the culprit. More specifically, the use of <code>openssl_random_pseudo_bytes()</code> when using PHP in forked child processes, as is the case when using PHP with Apache or PHP-FPM. The processes were wrapping, so the children would produce the same random sequences as previous children with the same process IDs.</p>
<p>Discovering this launched discussions on <a href="https://github.com/paragonie/random_compat/issues/96">what to do about OpenSSL</a> for the paragonie/random_compat library. After that project decided to drop the use of OpenSSL as a fallback for generating random bytes, I decided to require paragonie/random_compat as a dependency and use <code>random_bytes()</code> as the default random generator for ramsey/uuid. I then released versions 2.9.0 and 3.3.0 to provide versions in both 2.x and 3.x to solve this problem.</p>
<div class="embed rich Twitter"><blockquote class="twitter-tweet"><p lang="en" dir="ltr">ramsey/uuid 2.9.0 & 3.3.0 fix the UUID collision issue caused by OpenSSL. All users should upgrade. Thanks!<a href="https://t.co/N6Rwz1a5e2">https://t.co/N6Rwz1a5e2</a></p>— Ben Ramsey (@ramsey) <a href="https://twitter.com/ramsey/status/712357041822687232?ref_src=twsrc%5Etfw">March 22, 2016</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<p>It’s interesting to note that <a href="https://twitter.com/SwiftOnSecurity">@SwiftOnSecurity</a> picked up on the issue and posted about it:</p>
<div class="embed rich Twitter"><blockquote class="twitter-tweet"><p lang="en" dir="ltr">Fascinating investigation into developers getting tons of UUID collisions in small datasets (via <a href="https://twitter.com/CiPHPerCoder?ref_src=twsrc%5Etfw">@CiPHPerCoder</a>) <a href="https://t.co/apEOzx2m3B">https://t.co/apEOzx2m3B</a></p>— SwiftOnSecurity (@SwiftOnSecurity) <a href="https://twitter.com/SwiftOnSecurity/status/713596652192313345?ref_src=twsrc%5Etfw">March 26, 2016</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<h3 id="and-beyond">3.4.1 and Beyond</h3>
<p>ramsey/uuid has undergone many changes since its 1.0.0 release. That very first release had some severe limitations placed on it, due to the math involved. It also had some grievous bugs because of that math. I required that everyone using the library must use a 64-bit system, and I failed to factor in the unsignedness of the integers. Since all PHP integers are signed, this led to some serious problems in generating UUIDs.</p>
<p>The 2.x series of the library followed about seven months later, supporting both 64-bit and 32-bit systems and accounting for the unsignedness of UUID integers through the use of a BC math wrapper library, <a href="https://github.com/ramsey/moontoast-math">moontoast/math</a>. We—for it really was a community effort—made many improvements and enhancements over the course of the 2.x series, but it was clear that more flexibility was desired, and this led to the changes in the 3.x series.</p>
<p>The 3.x series ushered in a great deal of flexibility through interfaces and dependency injection. While the standard public API was left unchanged, all the guts of the library were completely transformed to allow anyone to use their own random generator, time provider, MAC address provider, and more.</p>
<p>Now, as the library matures beyond the 3.4.1 version, I’m looking ahead to the 4.x series, and how it will further improve the library with more flexibility and closer adherence to RFC 4122, while providing some facilities to optimize UUIDs in databases, and more.</p>
<p>Here are a handful of the issues I’m considering for 4.0.0. You can read more and may submit your own from the <a href="https://github.com/ramsey/uuid/issues">ramsey/uuid GitHub issues page</a>.</p>
<ul>
<li><a href="https://github.com/ramsey/uuid/issues/117">Store UUID in an optimized way for InnoDB</a></li>
<li><a href="https://github.com/ramsey/uuid/issues/116">Consider supporting version 2 DCE Security UUIDs</a></li>
<li><a href="https://github.com/ramsey/uuid/issues/110">Set lowest PHP version requirement to 5.6</a></li>
<li><a href="https://github.com/ramsey/uuid/issues/109">Use a math library other than moontoast/math</a></li>
<li><a href="https://github.com/ramsey/uuid/issues/90">Create DateTime with nanoseconds</a></li>
</ul>
<h3 id="how-to-use-it">How To Use It</h3>
<p>The ramsey/uuid library provides a static interface to create immutable UUID objects for RFC 4122 variant version 1, 3, 4, and 5 UUIDs. The preferred installation method is Composer:</p>
<figure class="code-highlight-figure"><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row unnumbered"><div class="code-highlight-line">composer require ramsey/uuid</div></div></pre></div></figure>
<p>After installation, simply require Composer’s autoloader (or use your own, or one provided by your framework of choice) and begin using the library right away, without any setup.</p>
<figure class="code-highlight-figure"><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="nv">$uuid</span> <span class="o">=</span> <span class="nx">\Ramsey\Uuid\Uuid</span><span class="o">::</span><span class="na">uuid4</span><span class="p">();</span>
</div></div><div data-line="2" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="k">echo</span> <span class="nv">$uuid4</span><span class="o">-></span><span class="na">toString</span><span class="p">();</span></div></div></pre></div></figure>
<p>The library will make some decisions about your environment and choose the best choices for generating random or time-based UUIDs, but these are configurable. For example, if you wish to use Anthony Ferrara’s <a href="https://github.com/ircmaxell/RandomLib">RandomLib</a> library as the random generator, you may configure the library to do so:</p>
<figure class="code-highlight-figure"><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="nv">$factory</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">\Ramsey\Uuid\UuidFactory</span><span class="p">();</span>
</div></div><div data-line="2" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="nv">$factory</span><span class="o">-></span><span class="na">setRandomGenerator</span><span class="p">(</span><span class="k">new</span> <span class="nx">\Ramsey\Uuid\Generator\RandomLibAdapter</span><span class="p">());</span>
</div></div><div data-line="3" class="code-highlight-row unnumbered"><div class="code-highlight-line"> </div></div><div data-line="4" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="nx">\Ramsey\Uuid\Uuid</span><span class="o">::</span><span class="na">setFactory</span><span class="p">(</span><span class="nv">$factory</span><span class="p">);</span>
</div></div><div data-line="5" class="code-highlight-row unnumbered"><div class="code-highlight-line"> </div></div><div data-line="6" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="nv">$uuid</span> <span class="o">=</span> <span class="nx">\Ramsey\Uuid\Uuid</span><span class="o">::</span><span class="na">uuid4</span><span class="p">();</span></div></div></pre></div></figure>
<p>If you wish to provide your own random generator, you may do so by implementing Ramsey\Uuid\Generator\RandomGeneratorInterface and setting your object as the random generator to use.</p>
<aside class="info"><blockquote><em>
<p>By default, ramsey/uuid uses <code>random_bytes()</code> to generate version 4 UUIDs. Since <code>random_bytes()</code> is available in PHP 7 and up, ramsey/uuid uses <a href="https://github.com/paragonie/random_compat">paragonie/random_compat</a> to provide a polyfill for earlier versions of PHP. In most cases, <code>random_bytes()</code> and its polyfill are sufficient random generators, and unless you have a special case, you should stick with the default.</p>
</em></blockquote></aside>
<p>Likewise, the library supports the ability to configure the time provider. If you’d like to use the PECL uuid package, for example, to generate time-based UUIDs, this is possible.</p>
<figure class="code-highlight-figure"><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="nv">$factory</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">\Ramsey\Uuid\UuidFactory</span><span class="p">();</span>
</div></div><div data-line="2" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="nv">$factory</span><span class="o">-></span><span class="na">setTimeGenerator</span><span class="p">(</span><span class="k">new</span> <span class="nx">\Ramsey\Uuid\Generator\PeclUuidTimeGenerator</span><span class="p">());</span>
</div></div><div data-line="3" class="code-highlight-row unnumbered"><div class="code-highlight-line"> </div></div><div data-line="4" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="nx">\Ramsey\Uuid\Uuid</span><span class="o">::</span><span class="na">setFactory</span><span class="p">(</span><span class="nv">$factory</span><span class="p">);</span>
</div></div><div data-line="5" class="code-highlight-row unnumbered"><div class="code-highlight-line"> </div></div><div data-line="6" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="nv">$uuid</span> <span class="o">=</span> <span class="nx">\Ramsey\Uuid\Uuid</span><span class="o">::</span><span class="na">uuid1</span><span class="p">();</span></div></div></pre></div></figure>
<p>There are a variety of other ways to configure ramsey/uuid. This example configures the library to generate a version 4 COMB sequential UUID with the timestamp as the first 48 bits.</p>
<figure class="code-highlight-figure"><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="nv">$factory</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">\Ramsey\Uuid\UuidFactory</span><span class="p">();</span>
</div></div><div data-line="2" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="nv">$generator</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">\Ramsey\Uuid\Generator\CombGenerator</span><span class="p">(</span><span class="nv">$factory</span><span class="o">-></span><span class="na">getRandomGenerator</span><span class="p">(),</span> <span class="nv">$factory</span><span class="o">-></span><span class="na">getNumberConverter</span><span class="p">());</span>
</div></div><div data-line="3" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="nv">$codec</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">\Ramsey\Uuid\Codec\TimestampFirstCombCodec</span><span class="p">(</span><span class="nv">$factory</span><span class="o">-></span><span class="na">getUuidBuilder</span><span class="p">());</span>
</div></div><div data-line="4" class="code-highlight-row unnumbered"><div class="code-highlight-line"> </div></div><div data-line="5" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="nv">$factory</span><span class="o">-></span><span class="na">setRandomGenerator</span><span class="p">(</span><span class="nv">$generator</span><span class="p">);</span>
</div></div><div data-line="6" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="nv">$factory</span><span class="o">-></span><span class="na">setCodec</span><span class="p">(</span><span class="nv">$codec</span><span class="p">);</span>
</div></div><div data-line="7" class="code-highlight-row unnumbered"><div class="code-highlight-line"> </div></div><div data-line="8" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="nx">\Ramsey\Uuid\Uuid</span><span class="o">::</span><span class="na">setFactory</span><span class="p">(</span><span class="nv">$factory</span><span class="p">);</span>
</div></div><div data-line="9" class="code-highlight-row unnumbered"><div class="code-highlight-line"> </div></div><div data-line="10" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="nv">$uuid</span> <span class="o">=</span> <span class="nx">\Ramsey\Uuid\Uuid</span><span class="o">::</span><span class="na">uuid4</span><span class="p">();</span></div></div></pre></div></figure>
<h3 id="thanks">Thanks</h3>
<p>I couldn’t wrap up this post without thanking a few key project contributors. Were it not for the efforts of these folks, ramsey/uuid would not be the great library it is today.</p>
<p>I want to first thank <a href="https://twitter.com/huizendveld">Marijn Huizendveld</a>. Marijn submitted the first pull requests to ramsey/uuid and contributed the Doctrine ORM integration that I later split out into the separate <a href="https://github.com/ramsey/uuid-doctrine">ramsey/uuid-doctrine</a> library. It was Marijn’s participation that got me excited about collaborating on an open source project and continuing the work.</p>
<p>I owe a debt of gratitude to <a href="https://twitter.com/ThibaudAztech">Thibaud Fabre</a> for his instrumental work in taking ramsey/uuid to version 3. He set out to re-architect the library, providing the interfaces and structure for codecs, generators, providers, and more. I’ve learned a lot about organizing software, object-oriented programming, and dependency injection from his involvement.</p>
<p>Most recent, <a href="https://twitter.com/JessicaMauerhan">Jessica Mauerhan</a> has been a force for improving our test suite, improving overall test coverage and adding tests for internal bits that were covered but not fully tested. I’ve learned a great deal about testing from her contributions.</p>
<p>Last but definitely not least, there are many more without whose contributions ramsey/uuid would be a lesser library. I am grateful to you all for your hard work and help in making ramsey/uuid an awesome library.</p>
<ul>
<li><a href="https://github.com/ramsey/uuid/graphs/contributors">List of ramsey/uuid contributors</a></li>
<li><a href="https://github.com/ramsey/uuid-doctrine/graphs/contributors">List of ramsey/uuid-doctrine contributors</a></li>
<li><a href="https://github.com/ramsey/uuid-console/graphs/contributors">List of ramsey/uuid-console contributors</a></li>
</ul>
<p>Cheers!</p>
<p><em><a rel="author" href="http://benramsey.com">Ben Ramsey</a> is a web developer, author, and speaker. He is a software architect at <a href="https://www.shootproof.com">ShootProof</a>, where he builds a platform for professional photographers. He enjoys organizing user groups and contributing to open source software. Ben blogs at <a href="http://benramsey.com">benramsey.com</a> and is <a href="https://twitter.com/ramsey">@ramsey</a> on Twitter.</em></p>
<p><small><em>“Introducing ramsey/uuid” was originally published at <a rel='bookmark' href='https://benramsey.com/blog/2016/04/ramsey-uuid/'>benramsey.com</a> and is Copyright © 2016 Ben Ramsey. It is licensed for use under a <a rel='license' type='text/html' href='http://creativecommons.org/licenses/by-sa/4.0/'>Creative Commons Attribution-ShareAlike license</a>.</em></small></p>
Hour of Code
2015-12-21T00:00:00+00:00
http://benramsey.com/blog/2015/12/hour-of-code
Copyright © 2015 Ben Ramsey.
I volunteered to help with an Hour of Code during Computer Science Education Week. This is my story, with a few tips to help when you volunteer.
<p><img width="100%" src="https://files.benramsey.com/ws/blog/2015-12-21-hour-of-code/banner-1500x630.jpg"></p>
<p>It was dark when I pulled into the parking lot of the middle school where I would spend the next hour volunteering for the <a href="https://code.org/learn">Hour of Code</a>. I had no idea what to expect. I hadn’t spoken much with the site coordinator, and I thought 5pm was an odd time to host the event.</p>
<p>I’ve spoken numerous times at many conferences but never about technology to middle-grades students. I wanted to instill in them a love for technology, but I wasn’t sure how to relate to them, and so I ran over and over in my head different scenarios of things I would say and questions they might ask. I was nervous on a different level.</p>
<p>“What if I say the wrong thing and turn them off to programming?”</p>
<p>“What if I bore them, and they think coding is boring?”</p>
<p>The school day had ended some time ago, and I walked along quiet, locker-lined halls, as I made my way to the classroom, smelling those once-familiar, musty smells of decades-old, concrete block school buildings. Down a hall, somewhere, a floor cleaning machine hummed, as a custodian buffed the white, vinyl tile floors. I recalled many hours I had spent at school after hours for extracurricular activities.</p>
<p>I spoke briefly to Kathy, the site coordinator, before entering the classroom, and I learned that the school has a variety of after-school programs their students participate in. This one happened to be the STEM program. They were mainly focused on conducting science experiments, but they decided to do the Hour of Code during <a href="https://csedweek.org/">Computer Science Education Week</a> this year. She had never done the Hour of Code and had requested a volunteer to help out. I was to be the one leading the entire program.</p>
<p>No problem. Winging things is my specialty. So, that’s what I did.</p>
<p>I spent a few minutes telling about what I do as a programmer on a daily basis, and I quickly realized that, while I’m passionate about what I do, it can sound rather banal when being explained to others, so I switched gears. I told them a brief version of my <a href="https://en.wikipedia.org/wiki/Origin_story">origin story</a>, so to speak.</p>
<p>I began with a question: “Who has ever written code?” No one raised their hands, so I pressed on.</p>
<p>“I wrote my first computer program when I was in fourth grade. It was a Mad Lib generator.” The students seemed to perk up and get interested at this.</p>
<p>I continued with my brief introduction to tell them that I went on to build my high school’s first web site back in 1995, but I never saw programming as a career. It had always been a hobby for me. Then, I stumbled into a job building web sites and doing sever-side programming, while I was still in college. It wasn’t until a professor convinced me to keep my job and drop the education requirements of my degree (student teaching, etc.) that I began to see my hobby as a career. I wanted to impress upon the students that careers don’t have to be boring things—they can be the things we are passionate and excited about. The things we enjoy doing in our free time are things that we can do for a living.</p>
<p>From there, I had them open up <a href="https://code.org/">code.org</a> on their Chromebooks and click the “Start learning” button. They chose the “Learn an Hour of Code” exercise that appealed most to them and proceeded to complete the steps. Some students breezed through the activities, while others struggled with the concepts. I used this as a teaching point, since my primary goal was to teach the students that failure and trial-and-error are natural parts of coding. If something doesn’t work the first time, then keep trying until it does work. Sometimes it takes many attempts before you get it.</p>
<p>After Kathy asked me several questions about the history of programming, I decided to wrap things up and try to answer her questions in a brief review of what the students had learned. I asked them what their favorite part of the exercise was and what they felt the most difficult part was. The answers varied. Then, I introduced a tiny bit of computer science history with a discussion of <a href="https://en.wikipedia.org/wiki/ENIAC">ENIAC</a>, <a href="https://en.wikipedia.org/wiki/Software_bug">bugs</a>, and <a href="https://en.wikipedia.org/wiki/Grace_Hopper">Grace Hopper</a>.</p>
<p>By then, our hour was up, and it was time for the students and myself to go. The time had been all-too-short, but I will volunteer again, and I learned a few things that I’ll keep in mind for the next time. I encourage you to volunteer, and I’m sharing my take-aways to help you when you do:</p>
<ul>
<li>Don’t spend a lot of time talking. Get the students right into the coding exercises.</li>
<li>Chances are, the teachers you are working with haven’t been through the Code.org exercises. If they contact you through the <a href="https://code.org/volunteer">Code.org volunteer site</a>, they probably think you’ll be prepared to lead the class. So, be prepared to lead.</li>
<li>Code.org provides teacher notes for each of their exercises. Familiarize yourself with the exercises and the notes.</li>
<li>Tell the students what you do for a living, but don’t focus too much on the specifics of your job. Our jobs are mostly boring to adolescents, unless we’re video game designers or movie animators.</li>
<li>Do tell what made you interested in coding and how you got started.</li>
<li>Tell about the first program you wrote.</li>
<li>Make sure you point out the importance of failure in writing code. Almost everything I have learned in coding has been a result of failure through trial-and-error. Students need to know how important this is.</li>
</ul>
<p><strong>Interested in volunteering for an Hour of Code near you? <a href="https://code.org/volunteer">Sign up here to have teachers contact you</a>.</strong></p>
<p><em><a rel="author" href="http://benramsey.com">Ben Ramsey</a> is a web developer, author, and speaker. He is a software architect at <a href="https://www.shootproof.com">ShootProof</a>, where he builds a platform for professional photographers. He enjoys organizing user groups and contributing to open source software. Ben blogs at <a href="http://benramsey.com">benramsey.com</a> and is <a href="https://twitter.com/ramsey">@ramsey</a> on Twitter.</em></p>
<p><small><em>“Hour of Code” was originally published at <a rel='bookmark' href='https://benramsey.com/blog/2015/12/hour-of-code/'>benramsey.com</a> and is Copyright © 2015 Ben Ramsey. It is licensed for use under a <a rel='license' type='text/html' href='http://creativecommons.org/licenses/by-sa/4.0/'>Creative Commons Attribution-ShareAlike license</a>.</em></small></p>
Yak Shaving Is the Entire Job Description
2015-11-30T00:00:00+00:00
http://benramsey.com/blog/2015/11/yak-shaving
Copyright © 2015 Ben Ramsey.
A recent struggle to solve a programming problem reminded me that yak shaving isn't just part of our jobs, it's the entire job description.
<p><img width="100%" src="https://files.benramsey.com/ws/blog/2015-11-30-yak-shaving/banner-1500x630.jpg"></p>
<p>Earlier this year, I worked on a solution to help us manage changes and history when maintaining different versions of Amazon Machine Images (AMIs). I entertained a wide range of ideas from <a href="https://www.docker.com/">Docker</a> to <a href="https://aws.amazon.com/cloudformation/">AWS CloudFormation</a> to a collection of shell scripts.</p>
<p>Finally, after asking in #pynash (Nashville’s Python user group) on Freenode IRC, <a href="http://jasonamyers.com/">Jason Myers</a> pointed me to <a href="https://packer.io/">Packer</a> as a potential solution.</p>
<blockquote>
<p>Packer is a tool for creating machine and container images for multiple platforms from a single source configuration.</p>
</blockquote>
<p>Packer turned out to be the right tool for the job, but I almost scrapped it, since I ran into a few problems.</p>
<p>When I began my journey as a programmer, every task was fraught with problems, and I loved it. Everything was new, and every problem was an opportunity to learn and grow. It was great.</p>
<p>Somewhere along the way, though, problems became nuisances. As I grew older in life and my career, my tolerance for problems became lower, and my desire for things to Just Work™ became greater.</p>
<p>As I struggled to find a solution for the problem I had with Packer, <a href="http://www.tateeskew.com/">Tate Eskew</a> reminded me that <a href="https://en.wiktionary.org/wiki/yak_shaving">yak shaving</a> is a part of my job.</p>
<figure class="code-highlight-figure"><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="nt"><teskew> </span>i'd just patch it, then. keep it in a central place so you only compile it once.
</div></div><div data-line="2" class="code-highlight-row numbered"><div class="code-highlight-line"> then when it's put into mainline, just switch out the binary
</div></div><div data-line="3" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="nt"><teskew> </span>either way, it's a pretty simple patch to test and change
</div></div><div data-line="4" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="nt"><ramsey> </span>ugh… gotta set up an environment just to build packer
</div></div><div data-line="5" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="nt"><ramsey> </span>"simple"
</div></div><div data-line="6" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="nt"><teskew> </span>you act like yak-shaving isn't the name of the game
</div></div><div data-line="7" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="nt"><ramsey> </span>:P
</div></div><div data-line="8" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="nt"><teskew> </span>hell, it's the entire job description
</div></div><div data-line="9" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="nt"><teskew> </span>:)
</div></div><div data-line="10" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="nt"><ramsey> </span>I am not an ops person
</div></div><div data-line="11" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="nt"><teskew> </span>you are right now :)</div></div></pre></div></figure>
<p>I ended up <a href="https://github.com/ramsey/packer/commit/016992bb5dcfdf9a62336ac135725cf0c1487ee4">patching Packer</a> for my needs, and I had fun doing it. I learned a valuable lesson that day: Despite how we may gripe and complain about shaving yaks, it’s part of our job as programmers and problem solvers, and often, it’s the part that brings us the most satisfaction. I’ve learned to embrace yak shaving, and doing so has changed my outlook on my job, open source contributions, and community organizing.</p>
<p>Yak shaving isn’t just part of our jobs, it’s the entire job description.</p>
<p><em><a rel="author" href="http://benramsey.com">Ben Ramsey</a> is a web developer, author, and speaker. He is a software architect at <a href="https://www.shootproof.com">ShootProof</a>, where he builds a platform for professional photographers. He enjoys organizing user groups and contributing to open source software. Ben blogs at <a href="http://benramsey.com">benramsey.com</a> and is <a href="https://twitter.com/ramsey">@ramsey</a> on Twitter.</em></p>
<p><small><em>“Yak Shaving Is the Entire Job Description” was originally published at <a rel='bookmark' href='https://benramsey.com/blog/2015/11/yak-shaving/'>benramsey.com</a> and is Copyright © 2015 Ben Ramsey. It is licensed for use under a <a rel='license' type='text/html' href='http://creativecommons.org/licenses/by-sa/4.0/'>Creative Commons Attribution-ShareAlike license</a>.</em></small></p>
Lack of Hypermedia
2015-11-27T00:00:00+00:00
http://benramsey.com/blog/2015/11/lack-of-hypermedia
Copyright © 2015 Ben Ramsey.
One of the most common problems I see in API development is lack of hypermedia, or none at all.
<p><a href="https://twitter.com/JustinRohrman">Justin Rohrman</a>, a former co-worker of mine, recently posted “<a href="http://blog.smartbear.com/apis/6-reasons-your-api-is-the-windows-vista-of-apis/">6 Reasons Your API is the Windows Vista of APIs</a>.” For his article, he asked me:</p>
<blockquote>
<p>I was wondering if you might give me a short description of what you see as one of the biggest API problems?</p>
</blockquote>
<p>I thought it might be helpful to post my full response, which follows:</p>
<p>One of the most common problems I see in API development is lack of hypermedia, or none at all. By hypermedia, I mean links that describe relationships among data in the API. When hypermedia isn’t used, the API becomes brittle, and those building clients that talk to the API are forced to code to URLs. The URLs become an important interface to the API, and if they change, they break everything. This leads to URL-based versioning schemes, and the only upgrade path for clients is to modify their code to accommodate the new versions.</p>
<p>When an API uses hypermedia, the URLs are no longer important. Clients talking to the API do not need to code to URLs because the API will always convey where to go next through hypermedia relationships. If a URL changes, then there’s no problem. The change gets communicated through the API. This leads to a more flexible and evolvable API that can change over time without needing to update all the clients.</p>
<p>I gave a talk at True North PHP this year that covered this topic. <a href="https://benramsey.com/talks/2015/11/truenorthphp-great-apis/">The slides are available for download.</a></p>
<p><em><a rel="author" href="http://benramsey.com">Ben Ramsey</a> is a web developer, author, and speaker. He is a software architect at <a href="https://www.shootproof.com">ShootProof</a>, where he builds a platform for professional photographers. He enjoys organizing user groups and contributing to open source software. Ben blogs at <a href="http://benramsey.com">benramsey.com</a> and is <a href="https://twitter.com/ramsey">@ramsey</a> on Twitter.</em></p>
<p><small><em>“Lack of Hypermedia” was originally published at <a rel='bookmark' href='https://benramsey.com/blog/2015/11/lack-of-hypermedia/'>benramsey.com</a> and is Copyright © 2015 Ben Ramsey. It is licensed for use under a <a rel='license' type='text/html' href='http://creativecommons.org/licenses/by-sa/4.0/'>Creative Commons Attribution-ShareAlike license</a>.</em></small></p>
Día de Muertos
2015-11-01T00:00:00+00:00
http://benramsey.com/blog/2015/11/dia-de-muertos
Copyright © 2015 Ben Ramsey.
Remembering PHP community members who have died.
<p><img width="100%" src="https://files.benramsey.com/ws/blog/2015-11-01-dia-de-muertos/banner-1500x630.jpg"></p>
<p>I’m fascinated by the Mexican traditions observed on <a href="https://en.wikipedia.org/wiki/Day_of_the_Dead">Día de Muertos</a>, or Day of the Dead. It’s a time for celebrating and remembering friends and family who have died.</p>
<p>This year, we have lost a few members of the PHP community, and on this Day of the Dead, I wanted to take a moment to remember some of the PHP community members who have died over the past few years.</p>
<p>If I am missing anyone, please use the comments to remember others, and leave your own remembrances for these.</p>
<dl>
<dt>Richard “Cyberlot” Thomas</dt>
<dd>I met Cyberlot first online in the <code>#phpc</code> IRC channel on Freenode. I saw him at occasional conferences, and I was sad to hear of his death in November 2010. He was an active contributor to the Solar framework project. Shortly after his death, <a href="http://web.archive.org/web/20101216031515/http://www.procata.com/blog/archives/2010/12/10/richard-thomas">Jeff Moore wrote a post remembering Cyberlot</a>.</dd>
<dt>Nick Jones</dt>
<dd>Nick was founder of the <a href="https://www.php-fusion.co.uk/">PHP-Fusion</a> project. The PHP-Fusion project maintains a <a href="https://www.php-fusion.co.uk/infusions/book_of_condolences/condolences.php">book of condolences</a> remembering his life and contributions.</dd>
<dt>Jeff Surgeson</dt>
<dd>Jeff was a contributor to the Aura and Solar framework projects.</dd>
<dt>Richard Lynch</dt>
<dd>Richard was one of the first people I met in the PHP community, having interacted with him a great deal on the php-general mailing list. He <a href="https://benramsey.com/blog/2015/07/chicago-php/">founded the Chicago PHP user group</a>, and was always willing to help newcomers with questions.</dd>
<dt>Jefferson McCree Jones</dt>
<dd>I met Jefferson first on IRC in the <code>#phpc</code> channel. He attended the second PHP Appalachia, and I began taking him to Atlanta PHP meetings. We were roommates at a number of conferences, and his enthusiasm for technology and jovial attitude touched many. Jefferson was a great friend. I miss him dearly.</dd>
<dt>Mike Dugan</dt>
<dd>Mike was an active member of the PHP community and frequent blogger. <a href="https://twitter.com/kayladnls">Kayla Daniels</a> set up a <a href="http://rememberingmikedugan.com/">memorial fund for his family</a> in his memory.</dd>
<dt>Alex King</dt>
<dd>Alex was a contributor to WordPress, having begun working with the project in its early b2 days. <a href="http://ma.tt/2015/09/remembering-alex-king/">Matt Mullenweg wrote a post remembering him</a>.</dd>
</dl>
<p><em><a rel="author" href="http://benramsey.com">Ben Ramsey</a> is a web developer, author, and speaker. He is a software architect at <a href="https://www.shootproof.com">ShootProof</a>, where he builds a platform for professional photographers. He enjoys organizing user groups and contributing to open source software. Ben blogs at <a href="http://benramsey.com">benramsey.com</a> and is <a href="https://twitter.com/ramsey">@ramsey</a> on Twitter.</em></p>
<p><small><em>“Día de Muertos” was originally published at <a rel='bookmark' href='https://benramsey.com/blog/2015/11/dia-de-muertos/'>benramsey.com</a> and is Copyright © 2015 Ben Ramsey. It is licensed for use under a <a rel='license' type='text/html' href='http://creativecommons.org/licenses/by-sa/4.0/'>Creative Commons Attribution-ShareAlike license</a>.</em></small></p>
Chicago PHP First Met in 2000, Not 1997
2015-07-28T00:00:00+00:00
2015-07-28T13:30:00+00:00
http://benramsey.com/blog/2015/07/chicago-php
Copyright © 2015 Ben Ramsey.
For many years, I’ve claimed that Chicago PHP held its first meeting in February of 1997. Unfortunately, I was wrong.
<p><img width="100%" src="https://files.benramsey.com/ws/blog/2015-07-27-chicago-php/banner-1500x630.jpg"></p>
<p>For many years, I’ve been claiming that Chicago PHP is the oldest, continuous-running PHP user group. This single fact hinged on <a href="http://web.archive.org/web/20061215165756/http://chiphpug.php.net/mpug.htm">a page</a> that, for many years, was hosted at <code>chiphpug.php.net</code> as a historical reference. On this page, it stated:</p>
<blockquote>
<p>The first meeting of the Midwest PHP User’s Group (MPUG) will be held at:</p>
<p>Saturday, February 26th, 1997, 1 pm CST <br />
Ignition State</p>
</blockquote>
<p>I’ve been passing along this information over the years to various members of the community. Most recent, I published it in an <a href="http://www.infoworld.com/article/2933858/php/php-at-20-from-pet-project-to-powerhouse.html">InfoWorld article reflecting on PHP at 20 years</a>. However, today this fact was called into question and debunked because <a href="https://twitter.com/Adduc/status/625712790913724416">John Long happened to link to an old mailing list post from 2000</a>.</p>
<p>In <a href="http://grokbase.com/t/php/php-version3/002vx7f6ar/ann-chiphpug-fka-mpug-meeting">the post dated February 26, 2000</a>, Richard Lynch says:</p>
<blockquote>
<p>The first Chicago PHP User’s Group, CHIPHPUG, [CHIF pug] meeting went very
well!</p>
<p>It was originally announced as MPUG, but even <em>I</em> didn’t really like that
name: It was just convenient. :-)</p>
</blockquote>
<p>After seeing this, I assumed the year must have been wrong. I thought maybe Grokbase had a bug, but then John pointed to <a href="http://news.php.net/php.version3/78555">the same post on news.php.net</a>. After this, I did some more exploring only to find <a href="http://grokbase.com/t/php/php-version3/002q7ffmrd/php3-ann-midwest-php-users-group-meeting">a post dated February 23, 2000</a>, where the “very first Midwest PHP User’s Group meeting” was announced.</p>
<p>The language used in the post was very similar to that found on the historical page; it’s missing the year.</p>
<blockquote>
<p>The very first Midwest PHP User’s Group meeting is definitely “on”:</p>
<p>Saturday, February 26th, 1 pm CST <br />
Ignition State</p>
</blockquote>
<p>This post also links to <code>http://www.L-I-E.com/MPUG.htm</code>, a page on Richard’s domain. I looked up <a href="http://web.archive.org/web/20000408233004/http://www.l-i-e.com/MPUG.htm">this page on the Internet Archive</a> to find that it is identical to the historical reference page that used to be hosted at <code>chiphpug.php.net</code>, with one exception. The year 1997 was erringly added to the historical reference page.</p>
<p>To confirm, I found the <a href="http://web.archive.org/web/20000818110408/http://chiphpug.php.net/">very first Internet Archive capture for chiphpug.php.net</a>, where it identifies the first meeting of the Chicago PHP user group as Saturday, February 26, 2000. It turns out February 26, 1997, was a Wednesday, while the historical reference page identified it as a Saturday, further proof the year was wrong.</p>
<p>I’m sorry for all the confusion I might have caused, and now that we know the truth, it’s time to find out which group really is the oldest, continuous-running PHP user group.</p>
<p><em><a rel="author" href="http://benramsey.com">Ben Ramsey</a> is a web developer, author, and speaker. He is a software architect at <a href="https://www.shootproof.com">ShootProof</a>, where he builds a platform for professional photographers. He enjoys organizing user groups and contributing to open source software. Ben blogs at <a href="http://benramsey.com">benramsey.com</a> and is <a href="https://twitter.com/ramsey">@ramsey</a> on Twitter.</em></p>
<p><small><em>“Chicago PHP First Met in 2000, Not 1997” was originally published at <a rel='bookmark' href='https://benramsey.com/blog/2015/07/chicago-php/'>benramsey.com</a> and is Copyright © 2015 Ben Ramsey. It is licensed for use under a <a rel='license' type='text/html' href='http://creativecommons.org/licenses/by-sa/4.0/'>Creative Commons Attribution-ShareAlike license</a>.</em></small></p>
Composer: Missing Distributions For Explict References
2015-06-17T22:30:00+00:00
2015-06-19T20:40:00+00:00
http://benramsey.com/blog/2015/06/composer-missing-distributions
Copyright © 2015 Ben Ramsey.
I prefer to hard-lock Composer dependencies for non-distributed apps, including hard-locking to a specific commit. Today, I encountered a problem…
<p><img width="100%" src="https://files.benramsey.com/ws/blog/2015-06-17-composer-missing-distributions/banner-1500x630.jpg"></p>
<aside class="success"><blockquote><em>
<p><a href="https://twitter.com/wim_vds">Wim Vandersmissen</a> was kind enough to correct this behavior with a <a href="https://github.com/composer/composer/pull/4167">pull request</a> to the Composer project, which <a href="http://seld.be/">Jordi</a> merged in. If you run <code>composer self-update</code>, it will update Composer with these changes, and <code>--prefer-dist</code> will behave properly to retrieve distribution zip archives for explicit references from Bitbucket.</p>
</em></blockquote></aside>
<p>This came as a bit of a surprise to me today, so I wanted to post it here to help others, in case you run into similar problems.</p>
<p>For applications I control that are not distributed to the public, I like to hard-lock my <a href="https://getcomposer.org/">Composer</a> dependencies to a specific version. I don’t use tilde, asterisk, caret, ranges, etc. to specify dependencies. I use the specific version number I want (i.e. <code>3.7.1</code>). This gives me piece of mind that application code I have already tested is not going to change behavior simply because underlying libraries I’m using have changed. It also gives me the flexibility to upgrade dependencies on my own terms.</p>
<aside class="danger"><blockquote><em><h5>Use Flexible Dependencies for Public Libraries</h5>
<p>I do not advocate this approach if you are developing a library for public distribution. Public libraries need to have flexible dependencies so that Composer can choose to the best possible version for other libraries requiring different versions of the same dependency.</p>
</em></blockquote></aside>
<p>Sometimes a library has updates that haven’t yet been released, and I need to use these right away. Composer allows me to specify the specific commit I want to use for a library. In this way, I can hard-lock a dependency to a specific state, even when there is not yet a release for the changes I need.</p>
<figure class="code-highlight-figure"><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="p">{</span>
</div></div><div data-line="2" class="code-highlight-row unnumbered"><div class="code-highlight-line"> <span class="nt">"require"</span><span class="p">:</span> <span class="p">{</span>
</div></div><div data-line="3" class="code-highlight-row unnumbered"><div class="code-highlight-line"> <span class="nt">"acme/foo"</span><span class="p">:</span> <span class="s2">"dev-master#b96ab0ce4a"</span>
</div></div><div data-line="4" class="code-highlight-row unnumbered"><div class="code-highlight-line"> <span class="p">}</span>
</div></div><div data-line="5" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="p">}</span></div></div></pre></div></figure>
<p>This has worked well until today, when I tried to do a fresh <code>composer install</code>. After installing, one library contained files and methods that I did not expect. It turns out Composer was grabbing the HEAD of dev-master instead of the specific commit I referenced.</p>
<p>When I looked in <code>vendor/composer/installed.json</code>, it became clear what was happening. The relevant entry looked a little something like this:</p>
<figure class="code-highlight-figure"><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="p">{</span>
</div></div><div data-line="2" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="nt">"name"</span><span class="p">:</span> <span class="s2">"acme/foo"</span><span class="p">,</span>
</div></div><div data-line="3" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="nt">"version"</span><span class="p">:</span> <span class="s2">"dev-master"</span><span class="p">,</span>
</div></div><div data-line="4" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="nt">"version_normalized"</span><span class="p">:</span> <span class="s2">"9999999-dev"</span><span class="p">,</span>
</div></div><div data-line="5" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="nt">"source"</span><span class="p">:</span> <span class="p">{</span>
</div></div><div data-line="6" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="nt">"type"</span><span class="p">:</span> <span class="s2">"git"</span><span class="p">,</span>
</div></div><div data-line="7" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="nt">"url"</span><span class="p">:</span> <span class="s2">"https://bitbucket.org/acme/foo.git"</span><span class="p">,</span>
</div></div><div data-line="8" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="nt">"reference"</span><span class="p">:</span> <span class="s2">"b96ab0ce4a"</span>
</div></div><div data-line="9" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="p">},</span>
</div></div><div data-line="10" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="nt">"dist"</span><span class="p">:</span> <span class="p">{</span>
</div></div><div data-line="11" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="nt">"type"</span><span class="p">:</span> <span class="s2">"zip"</span><span class="p">,</span>
</div></div><div data-line="12" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="nt">"url"</span><span class="p">:</span> <span class="s2">"https://bitbucket.org/acme/foo/get/03ae0dba64d1a902fb4d76004ef12c8391ededc8.zip"</span><span class="p">,</span>
</div></div><div data-line="13" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="nt">"reference"</span><span class="p">:</span> <span class="s2">"b96ab0ce4a"</span><span class="p">,</span>
</div></div><div data-line="14" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="nt">"shasum"</span><span class="p">:</span> <span class="s2">""</span>
</div></div><div data-line="15" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="p">},</span>
</div></div><div data-line="16" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="nt">"require"</span><span class="p">:</span> <span class="p">{</span>
</div></div><div data-line="17" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="nt">"php"</span><span class="p">:</span> <span class="s2">">=5.2.0"</span>
</div></div><div data-line="18" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="p">},</span>
</div></div><div data-line="19" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="nt">"time"</span><span class="p">:</span> <span class="s2">"2015-03-23 22:00:25"</span><span class="p">,</span>
</div></div><div data-line="20" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="nt">"type"</span><span class="p">:</span> <span class="s2">"library"</span><span class="p">,</span>
</div></div><div data-line="21" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="nt">"installation-source"</span><span class="p">:</span> <span class="s2">"dist"</span><span class="p">,</span>
</div></div><div data-line="22" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="nt">"autoload"</span><span class="p">:</span> <span class="p">{</span>
</div></div><div data-line="23" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="nt">"psr-0"</span><span class="p">:</span> <span class="p">{</span>
</div></div><div data-line="24" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="nt">"Acme"</span><span class="p">:</span> <span class="s2">"src/"</span>
</div></div><div data-line="25" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="p">}</span>
</div></div><div data-line="26" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="p">},</span>
</div></div><div data-line="27" class="code-highlight-row numbered"><div class="code-highlight-line"> <span class="nt">"description"</span><span class="p">:</span> <span class="s2">"An example library"</span>
</div></div><div data-line="28" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="p">}</span></div></div></pre></div></figure>
<p>Notice in line 21 that my installation-source is “dist,” and in the dist section it shows a zip file URL referring to a different commit hash than the reference (line 12 vs. line 13). This is because <a href="https://bitbucket.org/">Bitbucket</a> provides a distribution zip file for the current HEAD of the branch, but not the specific commit I need.</p>
<p>Since <code>composer install</code> uses <code>--prefer-dist</code> by default, I was getting the distribution zip file provided by Bitbucket for the HEAD of the master branch, rather than for the specific commit I needed.</p>
<aside class="info"><blockquote><em><h5>GitHub Provides a Zip Archive for Each Commit</h5>
<p>It appears that this problem does not exist on GitHub. GitHub provides the ability to download a zip archive of every single commit, and Composer grabs the correct distribution for the explicit reference.</p>
</em></blockquote></aside>
<p>When providing the <code>--prefer-source</code> option to <code>composer install</code>, I was able to retrieve the exact commit I wanted. Problem solved!</p>
<p>Unfortunately, using <code>--prefer-source</code> is slower and downloads VCS files (i.e. <code>.git/</code>), as well as files that are marked as <code>export-ignore</code> in <code>.gitattributes</code> (since Composer isn’t getting the exported distribution archive but is cloning the repository itself).</p>
<p><em><a rel="author" href="http://benramsey.com">Ben Ramsey</a> is a web developer, author, and speaker. He is a software architect at <a href="https://www.shootproof.com">ShootProof</a>, where he builds a platform for professional photographers. He enjoys organizing user groups and contributing to open source software. Ben blogs at <a href="http://benramsey.com">benramsey.com</a> and is <a href="https://twitter.com/ramsey">@ramsey</a> on Twitter.</em></p>
<p><small><em>“Composer: Missing Distributions For Explict References” was originally published at <a rel='bookmark' href='https://benramsey.com/blog/2015/06/composer-missing-distributions/'>benramsey.com</a> and is Copyright © 2015 Ben Ramsey. It is licensed for use under a <a rel='license' type='text/html' href='http://creativecommons.org/licenses/by-sa/4.0/'>Creative Commons Attribution-ShareAlike license</a>.</em></small></p>
Reflecting on PHP at 20
2015-06-11T21:30:00+00:00
2015-06-25T15:22:00+00:00
http://benramsey.com/blog/2015/06/php-at-20
Copyright © 2015 Ben Ramsey.
In this post, I discuss my InfoWorld article, @phpc's timeline, #20yearsofphp hashtag, PHP cake, and community posts reflecting on 20 years of PHP.
<p><img width="100%" src="https://files.benramsey.com/ws/blog/2015-06-11-php-at-20/banner-1500x630.jpg"></p>
<h3 id="infoworld-article-published">InfoWorld Article Published</h3>
<p>Today, my article “<a href="http://www.infoworld.com/article/2933858/php/php-at-20-from-pet-project-to-powerhouse.html" data-versionurl="http://web.archive.org/web/20150611131243/http://www.infoworld.com/article/2933858/php/php-at-20-from-pet-project-to-powerhouse.html" data-versiondate="2015-06-11">PHP at 20: From pet project to powerhouse</a>” was published in <a href="http://www.infoworld.com/">InfoWorld</a>. The article discusses the origins of PHP, how it and its community pride themselves in pragmatic approaches to solving problems, and how it is relevant and evolving today. It even got <a href="http://developers.slashdot.org/story/15/06/11/1659201/php-at-20-from-pet-project-to-powerhouse" data-versionurl="https://web.archive.org/web/20150611193021/http://developers.slashdot.org/story/15/06/11/1659201/php-at-20-from-pet-project-to-powerhouse" data-versiondate="2015-06-11">linked to from Slashdot</a>, which is exciting. Just don’t bother reading the comments. ;-)</p>
<p>I had a great time putting together this article, and the research I did jogged more than a few memories, allowing me to indulge in a bit of nostalgia.</p>
<blockquote>
<p>When Rasmus Lerdorf released “<a href="https://groups.google.com/d/msg/comp.infosystems.www.authoring.cgi/PyJ25gZ6z7A/M9FkTUVDfcwJ">a set of small tight CGI binaries written in C</a>,” he had no idea how much his creation would impact Web development. Delivering the opening keynote at this year’s SunshinePHP conference in Miami, Lerdorf quipped, “In 1995, I thought I had unleashed a C API upon the Web. Obviously, that’s not what happened, or we’d all be C programmers.”</p>
<p>[…]</p>
<p>Those early days speak volumes about PHP’s impact on Web development. Back then, our options were limited when it came to server-side processing for Web apps. PHP stepped in to fill our need for a tool that would enable us to do dynamic things on the Web. That practical flexibility captured our imaginations, and PHP has since grown up with the Web. Now powering <a href="http://w3techs.com/technologies/overview/programming_language/all">more than 80 percent of the Web</a>, PHP has matured into a scripting language that is especially suited to solve the Web problem. Its unique pedigree tells a story of pragmatism over theory and problem solving over purity.</p>
</blockquote>
<p>You may <a href="http://www.infoworld.com/article/2933858/php/php-at-20-from-pet-project-to-powerhouse.html" data-versionurl="http://web.archive.org/web/20150611131243/http://www.infoworld.com/article/2933858/php/php-at-20-from-pet-project-to-powerhouse.html" data-versiondate="2015-06-11">read the rest in InfoWorld</a>. I hope you like it.</p>
<h3 id="a-timeline-spanning-twenty-years">A Timeline Spanning Twenty Years</h3>
<p>Last weekend, an idea occurred to me to use the <a href="https://twitter.com/phpc">@phpc</a> Twitter account to celebrate PHP’s twentieth birthday in a unique way: by posting <a href="http://devzone.zend.com/6178/20yearsofphp-a-timeline-of-tweets/">a timeline of events in the PHP community</a> spanning the past twenty years. It was a lofty goal, and as I was wrapping up my InfoWorld article, I pieced together a timeline of events and scheduled them to be posted about every half hour.</p>
<div class="embed rich Twitter"><blockquote class="twitter-tweet"><p lang="en" dir="ltr">On 8 June 1995, <a href="https://twitter.com/rasmus?ref_src=twsrc%5Etfw">@rasmus</a> releases the source code for PHP Tools version 1.0. <a href="https://t.co/13WJfVo33b">https://t.co/13WJfVo33b</a> <a href="https://twitter.com/hashtag/20yearsofphp?src=hash&ref_src=twsrc%5Etfw">#20yearsofphp</a></p>— PHP Community (@phpc) <a href="https://twitter.com/phpc/status/607842014369968128?ref_src=twsrc%5Etfw">June 8, 2015</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<p>I regard each event in this timeline as important to the history of PHP, having shaped the language and community into what they are today. These events, however, are by no means the only important events. It was impossible to put together a complete list that included every project and every person who has made significant contributions to PHP and its community. I’m sorry if you and your project were left out, but please understand I do not intend any ill will.</p>
<p><a href="http://blog.calevans.com/">Cal Evans</a> was kind enough to capture the timeline in a <a href="https://storify.com/calevans/20yearsofphp">Storify</a> and post it on <a href="http://devzone.zend.com/6178/20yearsofphp-a-timeline-of-tweets/">Zend Developer Zone</a>. From there, you may read all the posts in the timeline.</p>
<h4 id="yearsofphp-hashtag">#20yearsofphp Hashtag</h4>
<p>I also advocated the use of the <a href="https://twitter.com/hashtag/20yearsofphp">#20yearsofphp hashtag</a> to help everyone follow along the conversation throughout the day.</p>
<p><a class="twitter-timeline" data-dnt="true" href="https://twitter.com/hashtag/20yearsofphp" data-widget-id="609105033112760320">#20yearsofphp Tweets</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script></p>
<h3 id="a-birthday-cake-for-php">A Birthday Cake for PHP</h3>
<p>For the June 2015 <a href="http://nashvillephp.org/">Nashville PHP</a> user group meeting this past Tuesday, I had some fun and got a cake so that our user group could join in the 20th birthday celebration. That’s our group in the cover photo for this post.</p>
<div class="box alt">
<div class="row 50% uniform">
<div class="6u">
<span class="image fit clean">
<a href="https://www.flickr.com/photos/benandliz/18530081769/"><img src="https://files.benramsey.com/ws/blog/2015-06-11-php-at-20/php-birthday-cake-1-1.jpg" /></a>
</span>
</div>
<div class="6u">
<span class="image fit clean">
<a href="https://www.flickr.com/photos/benandliz/18096515133/"><img src="https://files.benramsey.com/ws/blog/2015-06-11-php-at-20/php-birthday-cake-2.jpg" /></a>
</span>
</div>
</div>
</div>
<h3 id="the-community-reflects">The Community Reflects</h3>
<p>On Monday, I called for PHP developers to <a href="https://benramsey.com/blog/2015/06/20-years-of-php/">reflect on their first experiences discovering PHP and the PHP community</a> and tag it with <code>#20yearsofphp</code>. Many responded, and I’ve enjoyed reading everyone’s posts. Thank you to everyone who posted.</p>
<p><a href="http://blog.phpdeveloper.org/">Chris Cornutt</a> has already captured most of these posts on <a href="http://www.phpdeveloper.org/news/22797">PHPDeveloper.org’s list of 20 Years of PHP posts</a>. I’m maintaining my own list here as a way for me to keep track of them. If I’m missing a link to your post, let me know.</p>
<ul>
<li><a href="https://thephp.cc/news/2015/06/20-years-of-php-ab" data-versionurl="https://web.archive.org/web/20150615131926/https://thephp.cc/news/2015/06/20-years-of-php-ab" data-versiondate="2015-06-15">Arne Blankerts</a></li>
<li><a href="http://blogs.aws.amazon.com/php/post/Tx21S0POQBSHFAG/HaPHPy-20th-Birthday-to-PHP" data-versionurl="http://web.archive.org/web/20150609180129/http://blogs.aws.amazon.com/php/post/Tx21S0POQBSHFAG/HaPHPy-20th-Birthday-to-PHP" data-versiondate="2015-06-09">AWS SDK Team</a></li>
<li><a href="http://amandafolson.net/blog/2015/06/08/twenty-years-of-php/" data-versionurl="https://archive.is/dyXKz" data-versiondate="2015-06-09">Amanda Folson</a></li>
<li><a href="http://duodra.co/2015/06/08/minha-historia-com-php/" hreflang="pt-BR" data-versionurl="http://web.archive.org/web/20150609180813/http://duodra.co/2015/06/08/minha-historia-com-php/" data-versiondate="2015-06-09">Anderson Casimiro</a> (<a href="http://duodra.co/2015/06/08/my-story-with-php/" hreflang="en" data-versionurl="http://web.archive.org/web/20150609180857/http://duodra.co/2015/06/08/my-story-with-php/" data-versiondate="2015-06-09">English</a>)</li>
<li><a href="http://benramsey.com/blog/2015/06/20-years-of-php/" data-versionurl="https://web.archive.org/web/20150609181141/http://benramsey.com/blog/2015/06/20-years-of-php/" data-versiondate="2015-06-09">Ben Ramsey</a></li>
<li><a href="http://blog.calevans.com/2015/06/08/celebrating-20-years-of-php/" data-versionurl="https://web.archive.org/web/20150609181218/http://blog.calevans.com/2015/06/08/celebrating-20-years-of-php/" data-versiondate="2015-06-09">Cal Evans</a></li>
<li><a href="http://blog.wyrihaximus.net/2015/06/20-years-of-php/" data-versionurl="https://web.archive.org/web/20150609181250/http://blog.wyrihaximus.net/2015/06/20-years-of-php/" data-versiondate="2015-06-09">Cess-Jan Kiewiet</a></li>
<li><a href="http://littlehart.net/atthekeyboard/2015/06/08/php-created-this-monster/" data-versionurl="https://web.archive.org/web/20150609181321/http://littlehart.net/atthekeyboard/2015/06/08/php-created-this-monster/" data-versiondate="2015-06-09">Chris Hartjes</a></li>
<li><a href="http://ctankersley.com/2015/06/08/20-years-of-php/" data-versionurl="https://web.archive.org/web/20150609181349/http://ctankersley.com/2015/06/08/20-years-of-php/" data-versiondate="2015-06-09">Chris Tankersley</a></li>
<li><a href="http://www.hauser-wenz.de/s9y/index.php?/archives/294-20-Years-of-PHP!.html" data-versionurl="https://web.archive.org/web/20150609181454/http://www.hauser-wenz.de/s9y/index.php?/archives/294-20-Years-of-PHP!.html" data-versiondate="2015-06-09">Christian Wenz</a></li>
<li><a href="http://daveyshafik.com/archives/69164-celebrating-20-years-of-php.html" data-versionurl="https://web.archive.org/web/20150609181543/http://daveyshafik.com/archives/69164-celebrating-20-years-of-php.html" data-versiondate="2015-06-09">Davey Shafik</a></li>
<li><a href="https://daveismyname.com/my-php-story-20-years-of-php-bp" data-versionurl="https://web.archive.org/web/20150609181622/https://daveismyname.com/my-php-story-20-years-of-php-bp" data-versiondate="2015-06-09">David Carr</a></li>
<li><a href="http://pennedav.net/blog/article/8/" data-versionurl="https://web.archive.org/web/20150609181731/http://pennedav.net/blog/article/8/" data-versiondate="2015-06-09">David M. Penner</a></li>
<li><a href="http://davidstockton.com/php/happy-20th-birthday-php" data-versionurl="https://web.archive.org/web/20150609181807/http://davidstockton.com/php/happy-20th-birthday-php" data-versiondate="2015-06-09">David Stockton</a></li>
<li><a href="http://derickrethans.nl/20years-php.html" data-versionurl="https://web.archive.org/web/20150612034958/http://derickrethans.nl/20years-php.html" data-versiondate="2015-06-11">Derick Rethans</a></li>
<li><a href="http://bussola.code-squad.com/2015/06/10/20-anos-de-php-evoluir-e-sexy/" data-versionurl="https://web.archive.org/web/20150610183954/http://bussola.code-squad.com/2015/06/10/20-anos-de-php-evoluir-e-sexy/" date-versiondate="2015-06-10">Er Galvao Abbott</a></li>
<li><a href="https://laravel-news.com/2015/06/20-years-of-php/" data-versionurl="https://web.archive.org/web/20150612012746/https://laravel-news.com/2015/06/20-years-of-php/" data-versiondate="2015-06-11">Eric L. Barnes</a></li>
<li><a href="http://www.erikaheidi.com/blog/celebrating-php-twenty-years" data-versionurl="https://web.archive.org/web/20150609181836/http://www.erikaheidi.com/blog/celebrating-php-twenty-years" data-versiondate="2015-06-09">Erika Heidi</a></li>
<li><a href="http://harikt.com/blog/2015/06/17/20-years-of-php/" data-versionurl="https://web.archive.org/web/20150617183037/http://harikt.com/blog/2015/06/17/20-years-of-php/" data-versiondate="2015-06-17">Hari KT</a></li>
<li><a href="http://ilia.ws/archives/290-Happy-belated-20th-PHP!.html" data-versionurl="https://web.archive.org/web/20150613001430/http://ilia.ws/archives/290-Happy-belated-20th-PHP!.html" data-versiondate="2015-06-12">Ilia Alshanetsky</a></li>
<li><a href="https://www.in2it.be/2015/06/20-years-of-php/" data-versionurl="https://web.archive.org/web/20150610130648/https://www.in2it.be/2015/06/20-years-of-php/" data-versiondate="2015-06-10">in2it</a></li>
<li><a href="http://www.jackbarber.co.uk/blog/my-20yearsofphp-story" data-versionurl="https://web.archive.org/web/20150610131051/http://www.jackbarber.co.uk/blog/my-20yearsofphp-story" data-versiondate="2015-06-10">Jack Barber</a></li>
<li><a href="http://blog.krakjoe.ninja/2015/06/20-years-of-php.html" data-versionurl="https://web.archive.org/web/20150609181921/http://blog.krakjoe.ninja/2015/06/20-years-of-php.html" data-versiondate="2015-06-09">Joe Watkins</a></li>
<li><a href="http://bafford.com/2015/06/08/20-years-of-php/" data-versionurl="https://web.archive.org/web/20150609182000/http://bafford.com/2015/06/08/20-years-of-php/" data-versiondate="2015-06-09">John Bafford</a></li>
<li><a href="http://jonathas.com/20-years-of-php-and-me/" data-versionurl="https://web.archive.org/web/20150615133635/http://jonathas.com/20-years-of-php-and-me/" data-versiondate="2015-06-15">Jon Ribeiro</a></li>
<li><a href="http://seld.be/notes/20-years-and-9-days-of-php" data-versionurl="https://web.archive.org/web/20150617153557/http://seld.be/notes/20-years-and-9-days-of-php" data-versiondate="2015-06-17">Jordi Boggiano</a></li>
<li><a href="http://www.justincarmony.com/blog/2015/06/08/happy-birthday-php/" data-versionurl="https://web.archive.org/web/20150609182037/http://www.justincarmony.com/blog/2015/06/08/happy-birthday-php/" data-versiondate="2015-06-09">Justin Carmony</a></li>
<li><a href="http://kerryowston.co.uk/how-i-got-started-in-php" data-versionurl="https://web.archive.org/web/20150609182117/http://kerryowston.co.uk/how-i-got-started-in-php" data-versiondate="2015-06-09">Kerry Owston</a></li>
<li><a href="http://kirstiehaxby.com/development/20-years-of-php-echo-mystory" data-versionurl="https://web.archive.org/web/20150619150420/http://kirstiehaxby.com/development/20-years-of-php-echo-mystory" data-versiondate="2015-06-19">Kirstie McMillan</a></li>
<li><a href="http://www.phpclasses.org/blog/post/293-20-Years-of-PHP-and-16-Years-of-PHP-Classes.html" data-versionurl="https://web.archive.org/web/20150625152226/http://www.phpclasses.org/blog/post/293-20-Years-of-PHP-and-16-Years-of-PHP-Classes.html" data-versiondate="2015-06-25">Manuel Lemos</a></li>
<li><a href="https://markrailton.com/blog/2015/06/08/20-years-of-php/" data-versionurl="https://archive.is/uVWVO" data-versiondate="2015-06-09">Mark Railton</a></li>
<li><a href="http://www.praterraines.co.uk/news/2015/0000041/my-php-story" data-versionurl="https://web.archive.org/web/20150609182548/http://www.praterraines.co.uk/news/2015/0000041/my-php-story" data-versiondate="2015-06-09">Matt Raines</a></li>
<li><a href="http://www.matthewsetter.com/happy-20th-birthday-php/" data-versionurl="https://web.archive.org/web/20150609182632/http://www.matthewsetter.com/happy-20th-birthday-php/" data-versiondate="2015-06-09">Matthew Setter</a></li>
<li><a href="https://mwop.net/blog/2015-06-08-php-is-20.html" data-versionurl="https://web.archive.org/web/20150609182705/https://mwop.net/blog/2015-06-08-php-is-20.html" data-versiondate="2015-06-09">Matthew Weier O’Phinney</a></li>
<li><a href="http://www.dragonbe.com/2015/06/20-years-of-php.html" data-versionurl="https://web.archive.org/web/20150609182735/http://www.dragonbe.com/2015/06/20-years-of-php.html" data-versiondate="2015-06-09">Michelangelo van Dam</a></li>
<li><a href="http://oscarm.org/2015/06/20-years-of-php/" data-versionurl="https://web.archive.org/web/20150609183146/http://oscarm.org/2015/06/20-years-of-php/" data-versiondate="2015-06-09">Oscar Merida</a></li>
<li><a href="http://blog.pascal-martin.fr/post/php-a-20-ans.html" hreflang="fr" data-versionurl="https://web.archive.org/web/20150609183322/http://blog.pascal-martin.fr/post/php-a-20-ans.html" data-versiondate="2015-06-09">Pascal Martin</a></li>
<li><a href="http://www.patrickstephan.me/post/20-years-with-PHP.html" data-versionurl="https://web.archive.org/web/20150610134604/http://www.patrickstephan.me/post/20-years-with-PHP.html" data-versiondate="2015-06-10">Patrick Stephan</a></li>
<li><a href="http://www.pauloeduardo.com/2015/06/08/20-anos-de-php/" hreflang="pt" data-versionurl="https://web.archive.org/web/20150609183620/http://www.pauloeduardo.com/2015/06/08/20-anos-de-php/" data-versiondate="2015-06-09">Paulo Eduardo</a></li>
<li><a href="http://monoforms.com/content/twenty-years-php" hreflang="es" data-versionurl="https://web.archive.org/web/20150609183802/http://monoforms.com/content/twenty-years-php" data-versiondate="2015-06-09">Peter Activar</a></li>
<li><a href="http://blog.doh.ms/2015/06/08/20-years-of-php-and-how-i-got-on-this-train/" data-versionurl="https://web.archive.org/web/20150609184344/http://blog.doh.ms/2015/06/08/20-years-of-php-and-how-i-got-on-this-train/" data-versiondate="2015-06-09">Rafael Dohms</a></li>
<li><a href="http://akrabat.com/20-years-of-php/" data-versionurl="https://web.archive.org/web/20150609184450/http://akrabat.com/20-years-of-php/" data-versiondate="2015-06-09">Rob Allen</a></li>
<li><a href="https://thephp.cc/news/2015/06/20-years-of-php-sb" data-versionurl="https://web.archive.org/web/20150611130755/https://thephp.cc/news/2015/06/20-years-of-php-sb" data-versiondate="2015-06-11">Sebastian Bergmann</a></li>
<li><a href="http://blog.shameerc.com/2015/06/haphpy-20th-birthday-php" data-versionurl="https://web.archive.org/web/20150609184527/http://blog.shameerc.com/2015/06/haphpy-20th-birthday-php" data-versiondate="2015-06-09">Shameer C</a></li>
<li><a href="http://blog.sheriframadan.com/20-years-of-PHP.html" data-versionurl="https://web.archive.org/web/20150610130410/http://blog.sheriframadan.com/20-years-of-PHP.html" data-versiondate="2015-06-10">Sherif Ramadan</a></li>
<li><a href="http://simonrjones.net/2015/06/php-and-me/" data-versionurl="https://web.archive.org/web/20150609184554/http://simonrjones.net/2015/06/php-and-me/" data-versiondate="2015-06-09">Simon R. Jones</a></li>
<li><a href="https://thephp.cc/news/2015/06/20-years-of-php-sp" data-versionurl="https://web.archive.org/web/20150612142125/https://thephp.cc/news/2015/06/20-years-of-php-sp" data-versiondate="2015-06-12">Stefan Priebsch</a></li>
<li><a href="https://blog.bitexpert.de/blog/20-years-of-php/" data-versionurl="https://web.archive.org/web/20150609184652/https://blog.bitexpert.de/blog/20-years-of-php/" data-versiondate="2015-06-09">Stephan Hochdörfer</a></li>
<li><a href="http://tudorbarbu.ninja/20-years-of-php/" data-versionurl="https://web.archive.org/web/20150609184724/http://tudorbarbu.ninja/20-years-of-php/" data-versiondate="2015-06-09">Tudor Barbu</a></li>
<li><a href="http://www.vectormediagroup.com/blog/view/celebrating-20-years-of-php" data-versionurl="https://web.archive.org/web/20150611181457/http://www.vectormediagroup.com/blog/view/celebrating-20-years-of-php" data-versiondate="2015-06-11">Vector Media Group</a></li>
<li><a href="http://wellingguzman.com/notes/twenty-years-of-php" data-versionurl="https://web.archive.org/web/20150618134321/http://wellingguzman.com/notes/twenty-years-of-php" data-versiondate="2015-06-18">Welling Guzman</a></li>
<li><a href="http://techblog.wimgodden.be/2015/06/08/a-happy-20-years/" data-versionurl="https://web.archive.org/web/20150609185113/http://techblog.wimgodden.be/2015/06/08/a-happy-20-years/" data-versiondate="2015-06-09">Wim Godden</a></li>
</ul>
<p><em><a rel="author" href="http://benramsey.com">Ben Ramsey</a> is a web developer, author, and speaker. He is a software architect at <a href="https://www.shootproof.com">ShootProof</a>, where he builds a platform for professional photographers. He enjoys organizing user groups and contributing to open source software. Ben blogs at <a href="http://benramsey.com">benramsey.com</a> and is <a href="https://twitter.com/ramsey">@ramsey</a> on Twitter.</em></p>
<p><small><em>“Reflecting on PHP at 20” was originally published at <a rel='bookmark' href='https://benramsey.com/blog/2015/06/php-at-20/'>benramsey.com</a> and is Copyright © 2015 Ben Ramsey. It is licensed for use under a <a rel='license' type='text/html' href='http://creativecommons.org/licenses/by-sa/4.0/'>Creative Commons Attribution-ShareAlike license</a>.</em></small></p>
20 Years of PHP
2015-06-08T12:00:00+00:00
2015-06-15T13:20:00+00:00
http://benramsey.com/blog/2015/06/20-years-of-php
Copyright © 2015 Ben Ramsey.
Twenty years ago today, Rasmus Lerdorf released Personal Home Page Tools (PHP Tools) version 1.0 to the world. I first encountered PHP in early 2000…
<p><img width="100%" src="https://files.benramsey.com/ws/blog/2015-06-08-20-years-of-php/banner-1500x630.jpg"></p>
<p>Twenty years ago today, <a href="https://groups.google.com/forum/#!msg/comp.infosystems.www.authoring.cgi/PyJ25gZ6z7A/M9FkTUVDfcwJ">Rasmus Lerdorf released Personal Home Page Tools</a> (PHP Tools) version 1.0 to the world.</p>
<aside class="info"><blockquote><em><h5>Reflecting on PHP at 20</h5>
<p>Please check out my newer post “<a href="https://benramsey.com/blog/2015/06/php-at-20/">Reflecting on PHP at 20</a>,” where I discuss my InfoWorld article “<a href="http://www.infoworld.com/article/2933858/php/php-at-20-from-pet-project-to-powerhouse.html" data-versionurl="http://web.archive.org/web/20150611131243/http://www.infoworld.com/article/2933858/php/php-at-20-from-pet-project-to-powerhouse.html" data-versiondate="2015-06-11">PHP at 20: From pet project to powerhouse</a>”, <a href="http://devzone.zend.com/6178/20yearsofphp-a-timeline-of-tweets/">@phpc’s timeline</a>, the <a href="https://twitter.com/hashtag/20yearsofphp">#20yearsofphp</a> hashtag, PHP cake, and community posts reflecting on 20 years of PHP.</p>
</em></blockquote></aside>
<p>I first encountered PHP in early 2000 when I was working for <a href="https://twitter.com/brianrudolph">Brian Rudolph</a> at <a href="http://web.archive.org/web/20040802224013/http://www.eureka-interactive.com/eugene.html">EUREKA! Interactive</a>. It was my first, big job in the industry, and it provided a solid foundation for the rest of my career.</p>
<p>As I recall, I was making changes to a website, and I used an FTP program—probably <a href="http://en.wikipedia.org/wiki/CuteFTP">CuteFTP</a>—to connect to the server to access the files. I remember seeing files in the directory with the extension <code>.php3</code>. That didn’t strike me as odd, though. I had certainly seen these file extensions in URLs before, but my server-side programming experience up until this point had included only Perl and <a href="http://en.wikipedia.org/wiki/Active_Server_Pages">Classic ASP</a>. I was able to open up the files, navigate around the PHP tags to make the necessary changes, and save the files back to the server—making updates directly to production, as one does.</p>
<p>It wasn’t until 2002 that I began using PHP extensively—I wrote at length about that ten years ago for <a href="https://benramsey.com/blog/2005/06/happy-birthday-php/">PHP’s tenth birthday celebration</a>—but this was my first encounter with it, and the thing that struck me was its ease-of-use. Now, fifteen years later, I look back on a career that has been made possible because of PHP.</p>
<p>How did you first encounter PHP? For PHP’s twentieth birthday, I’d like to encourage you to post your own PHP story on your blog. Then, post it to Twitter using the hashtag <code>#20yearsofphp</code>. Also, be sure to follow along as <a href="https://twitter.com/phpc">@phpc</a> posts PHP community milestones throughout the day.</p>
<p><em><a rel="author" href="http://benramsey.com">Ben Ramsey</a> is a web developer, author, and speaker. He is a software architect at <a href="https://www.shootproof.com">ShootProof</a>, where he builds a platform for professional photographers. He enjoys organizing user groups and contributing to open source software. Ben blogs at <a href="http://benramsey.com">benramsey.com</a> and is <a href="https://twitter.com/ramsey">@ramsey</a> on Twitter.</em></p>
<p><small><em>“20 Years of PHP” was originally published at <a rel='bookmark' href='https://benramsey.com/blog/2015/06/20-years-of-php/'>benramsey.com</a> and is Copyright © 2015 Ben Ramsey. It is licensed for use under a <a rel='license' type='text/html' href='http://creativecommons.org/licenses/by-sa/4.0/'>Creative Commons Attribution-ShareAlike license</a>.</em></small></p>
Fun Recruiter Messages
2015-05-28T22:00:00+00:00
http://benramsey.com/blog/2015/05/fun-recruiter-messages
Copyright © 2015 Ben Ramsey.
Earlier today in the #coderabbi Freenode IRC channel, we were discussing recruiter messages. I thought I’d share one of my favorite gems from over the years.
<p>Earlier today in the <code>#coderabbi</code> Freenode IRC channel, we were discussing recruiter messages. I thought I’d share one of my favorite gems from over the years.</p>
<blockquote>
<p>Would you like to join one of the fastest growing start-ups in Rhode Island? Would you like to be apart [sic] company that makes dreams come true? If you are passionate about Ruby and Opensource technology development than [sic] this is the place for you. Wouldn’t it be nice to come home every day and know you are doing what you love in a company that loves your work? This is not just your average “job”. This is opportunity; this is a blur between dreams and reality; this is the opportunity that is going to slingshot you to happiness & career satisfaction.</p>
</blockquote>
<p>Without shaming, ridiculing, or calling out any individuals, what’s your favorite recruiter message?</p>
<p><em><a rel="author" href="http://benramsey.com">Ben Ramsey</a> is a web developer, author, and speaker. He is a software architect at <a href="https://www.shootproof.com">ShootProof</a>, where he builds a platform for professional photographers. He enjoys organizing user groups and contributing to open source software. Ben blogs at <a href="http://benramsey.com">benramsey.com</a> and is <a href="https://twitter.com/ramsey">@ramsey</a> on Twitter.</em></p>
<p><small><em>“Fun Recruiter Messages” was originally published at <a rel='bookmark' href='https://benramsey.com/blog/2015/05/fun-recruiter-messages/'>benramsey.com</a> and is Copyright © 2015 Ben Ramsey. It is licensed for use under a <a rel='license' type='text/html' href='http://creativecommons.org/licenses/by-sa/4.0/'>Creative Commons Attribution-ShareAlike license</a>.</em></small></p>
Website Redesign
2015-05-26T13:00:00+00:00
http://benramsey.com/blog/2015/05/website-redesign
Copyright © 2015 Ben Ramsey.
I’ve fully redesigned my website and have added more content. In this post, I explain why and how.
<p><img width="100%" src="https://files.benramsey.com/ws/blog/2015-05-25-website-redesign/banner-1500x630.jpg"></p>
<p class="lead-in">Welcome to my brand new website! I’ve worked hard to make this site, and I hope you like it.</p>
<p>My blog has been around since 2004. My first blog post was written about the <a href="https://benramsey.com/blog/2004/02/phpcommunityorg/">PHP Community project</a>. Back then, I used <a href="http://en.wikipedia.org/wiki/Movable_Type">Movable Type</a> as my blogging engine. WordPress was still young, having only recently been forked from <a href="http://cafelog.com/">b2</a>. A few months later, <a href="https://benramsey.com/blog/2004/08/switching-to-wordpress/">I did switch to WordPress</a>, and then many years after that, I decided to use a static site generator, so <a href="https://benramsey.com/blog/2012/02/revamping-my-development-toolchain/">I switched to Octopress</a>.</p>
<h3 id="why-redesign">Why Redesign?</h3>
<p>There were several things that prompted my desire to redesign this website:</p>
<p>For one, I was inspired by the branding efforts of <a href="http://wisdomworldtour.com/">Yitzchok Willroth</a>, <a href="http://www.grumpy-learning.com/">Chris Hartjes</a>, and <a href="http://shiflett.org/">Chris Shiflett</a>, and I wanted a personal web presence that would better communicate who I am and what I do.</p>
<p>Second, I wanted a project that would take me back to my web development roots, and I felt that developing a personal website with all the bells and whistles would do just that. Through this process, I’ve been able to learn more about HTML5 and CSS3, as well as responsive website development.</p>
<p>Last, I wanted to encourage and inspire others to follow suit. A decade ago, most web thought leadership conversations took place across blogs, and from blogs, leaders innovated and led the development of the <a href="http://en.wikipedia.org/wiki/Open_Web">Open Web</a>. However, since the advent of closed, microblogging platforms, many (myself included) have left their blogs behind in the dust, and I feel we’ve lost some of that innovation and openness. This redesign represents the beginning of my return to the ideals of the Open Web.</p>
<div class="embed rich Twitter"><blockquote class="twitter-tweet"><p lang="en" dir="ltr">Loving all the little touches in <a href="https://twitter.com/ramsey?ref_src=twsrc%5Etfw">@ramsey</a>’s redesign. He even has a /purpose! :-) <a href="http://t.co/RaPmYmhNZf">http://t.co/RaPmYmhNZf</a></p>— Chris Shiflett (@shiflett) <a href="https://twitter.com/shiflett/status/601779406978285568?ref_src=twsrc%5Etfw">May 22, 2015</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<h3 id="purpose">/Purpose</h3>
<p>Why do you do what you do? I am a web developer because I believe the web has the power to change the world. It is the biggest communications tool of our time, and it has the greatest power to effect change—if used appropriately. I have a passion for teaching web development because I want to encourage others to use these skills to change the world for good.</p>
<p>I have been inspired by my friends at <a href="http://fictivekin.com/">Fictive Kin</a> to create a <a href="http://slashpurpose.org/">/purpose</a> (Slash Purpose) page, and I encourage you to think about why you do what you do and create your own /purpose page. Let it drive all that you do.</p>
<p>Here is <a href="https://benramsey.com/purpose/">my /purpose page</a>.</p>
<h3 id="indieweb-movement">IndieWeb Movement</h3>
<p>Through Chris Shiflett, I found out about the <a href="https://indiewebcamp.com/">Indie Web</a> movement. Almost immediately, I felt a kinship with this community. I’ve already mentioned the Open Web philosophy. The Indie Web movement seems to be taking steps in this direction. I have followed their “<a href="https://indiewebcamp.com/Get_Started">Getting Started</a>” guide to mark up my website with authorship information (h-card) and microformats mark-up for blog posts and articles (h-entry). This means my site content is easy to scrape, and it provides good identity information about myself that machines can read.</p>
<p>Chris has <a href="http://shiflett.org/blog/2015/may/indie-web-movement-and-indieauth">written a little about some of the practical applications of IndieAuth</a>. I’m sure he’ll write more, so I encourage you to follow along.</p>
<h3 id="focus-on-content">Focus on Content</h3>
<p>Previous versions of my website included only my blog and did not focus on my talks, articles, books, or projects. It is important to me to showcase this content, and so this new version of my site includes these and more. Just take a look under the <em>Features</em> navigation link up top, or follow these links:</p>
<dl>
<dt><a href="https://benramsey.com/blog/">Blog</a></dt>
<dd>I write about web development and related technologies in my blog. Usually, it has something to do with PHP. Occasionally, I’m off-topic.</dd>
<dt><a href="https://benramsey.com/articles/">Articles</a></dt>
<dd>Here you can find my published articles with some useful and current discussion in the comments.</dd>
<dt><a href="https://benramsey.com/books/">Books</a></dt>
<dd>Here you can find more information about books and publications I’ve written and contributed to.</dd>
<dt><a href="https://benramsey.com/talks/">Talks</a></dt>
<dd>I speak about web development and related technologies at conferences around the world.</dd>
<dt><a href="https://benramsey.com/projects/">Projects</a></dt>
<dd>I organize, maintain, develop, and participate in many open source projects and communities.</dd>
<dt><a href="https://benramsey.com/brews/">Brews</a></dt>
<dd>I am an aficionado of beer and lover of coffee. Sometimes I write about them.</dd>
</dl>
<h3 id="simple-and-elegant-design">Simple and Elegant Design</h3>
<p>I am a web developer, not a designer. I wanted something simple, elegant, and responsive that reflected my own personality, but I knew I would be unable to pull it off on my own.</p>
<p>For design inspiration, I turned to <a href="http://html5up.net/">HTML5 UP</a>. These are all clean and simple designs that are responsive, built with HTML5 and CSS3, and are licensed for free under a Creative Commons license. Through HTML5 UP, I learned about <a href="http://twitter.com/n33co">AJ’s</a> other project, <a href="http://pixelarity.com/">Pixelarity</a>. From there, I found the Catalyst theme, which is the theme on which I based this website.</p>
<p>Thanks, AJ! I see you’re also in Nashville. Maybe I can buy you a drink sometime. :-)</p>
<h3 id="tools-used">Tools Used</h3>
<p>I again chose to use a static site generator for this website. I was pleased with how well Octopress worked, and I was interested in the forthcoming <a href="https://github.com/octopress/octopress">Octopress 3</a>. Octopress 3 is still in the development stages, so I used <a href="http://jekyllrb.com/">Jekyll</a> as the base, with a mixture of Jekyll and Octopress plugins, as well as some of my own.</p>
<p>For the most part, I write all my posts and pages in Markdown, and I’ve been very happy with the <a href="http://kramdown.gettalong.org/">kramdown</a> Markdown-superset converter. Additionally, I’m a big fan of <a href="http://pygments.org/">Pygments</a> coupled with the <a href="https://github.com/octopress/codefence">Octopress Codefence</a> plugin for marking up source code and providing syntax highlighting.</p>
<p>Before you ask why I didn’t use <a href="https://sculpin.io/">Sculpin</a>, let me take a moment to explain. Sculpin is a static site generator written in PHP. I love the project and the community around it. In fact, to show my support for it, I began this project by using Sculpin as its engine. However, after spending several months with it, I decided it wasn’t going to meet my needs or help me accomplish my goals; I was spending far too much time hacking the engine and writing Symfony bundles for functionality that didn’t yet exist in Sculpin.</p>
<p>So, to <a href="https://beau.io/">Beau</a> and the rest of the Sculpin contributors, I really do like what you’re doing and I encourage you to keep at it. I think it’s an exciting project, and in the future, I’d like to switch back to Sculpin. My wish list for Sculpin would include a focus on interop with Jekyll/Liquid and streamlined ability to create and install plugins.</p>
<h3 id="behind-the-scenes">Behind the Scenes</h3>
<p>I’ve already mentioned HTML5 and CSS3, and in putting together this website, I got to learn the JavaScript framework <a href="http://getskel.com/">Skel</a> and I was able to play with the <a href="http://sass-lang.com/">Sass</a> CSS extension language. Both are used heavily by HTML5 UP and Pixelarity themes. In fact, I found Skel much more flexible and useful for defining and managing responsive breakpoints than the popular <a href="http://getbootstrap.com/">Bootstrap</a> framework.</p>
<p>My website is hosted in <a href="http://aws.amazon.com/s3/">Amazon S3</a>, with many static assets being served through <a href="http://aws.amazon.com/cloudfront/">Amazon CloudFront</a>. I deploy to S3 using <a href="http://s3tools.org/s3cmd">s3cmd</a>, and I manage redirects in S3 using <a href="https://github.com/nathangrigg/s3redirect">s3redirect</a>. I’ve tried to ensure that all old URLs in my site, from 2004 to present day, redirect properly.</p>
<h3 id="benramseycom-through-the-years">Benramsey.com Through the Years</h3>
<p>Here are a few links to my website as it has appeared through the years:</p>
<ul>
<li><a href="https://web.archive.org/web/20040311161922/http://benramsey.com/blog/">First capture on the Wayback Machine</a> (March 2004)</li>
<li><a href="https://web.archive.org/web/20050208154541/http://blog.benramsey.com/">After switching to WordPress</a> (February 2005)</li>
<li><a href="https://web.archive.org/web/20050406033626/http://benramsey.com/">New design using a downloaded WordPress theme</a> (April 2005)</li>
<li><a href="https://web.archive.org/web/20051211101820/http://benramsey.com/">New design of my own imagining and handiwork</a> (December 2005)</li>
<li><a href="https://web.archive.org/web/20101227032354/http://benramsey.com/">Five years later, I was still using the same design</a> (December 2010)</li>
<li><a href="https://web.archive.org/web/20120120034054/http://benramsey.com/">Save the Internet blackout page</a> (January 2012)</li>
<li><a href="https://web.archive.org/web/20120219220340/http://benramsey.com/">First Wayback Machine capture after switching to Octopress</a> (February 2012)</li>
</ul>
<p><em><a rel="author" href="http://benramsey.com">Ben Ramsey</a> is a web developer, author, and speaker. He is a software architect at <a href="https://www.shootproof.com">ShootProof</a>, where he builds a platform for professional photographers. He enjoys organizing user groups and contributing to open source software. Ben blogs at <a href="http://benramsey.com">benramsey.com</a> and is <a href="https://twitter.com/ramsey">@ramsey</a> on Twitter.</em></p>
<p><small><em>“Website Redesign” was originally published at <a rel='bookmark' href='https://benramsey.com/blog/2015/05/website-redesign/'>benramsey.com</a> and is Copyright © 2015 Ben Ramsey. It is licensed for use under a <a rel='license' type='text/html' href='http://creativecommons.org/licenses/by-sa/4.0/'>Creative Commons Attribution-ShareAlike license</a>.</em></small></p>
My Failed Attempts at Soft Skills Talks
2015-05-23T20:30:00+00:00
2015-06-25T14:42:00+00:00
http://benramsey.com/blog/2015/05/my-failed-attempts-at-soft-skills-talks
Copyright © 2015 Ben Ramsey.
In 2013, I began crafting soft skills talks as a return to the PHP conference speaker circuit, but I learned I wasn't suited to deliver these talks.
<p><img width="100%" src="https://files.benramsey.com/ws/blog/2015-05-23-my-failed-attempts-at-soft-skills-talks/banner-1500x630.jpg"></p>
<p>During the <a href="http://devhell.info/">Development Hell</a> podcast recording at <a href="http://tek15.phparch.com/">php[tek]</a> (<del>not yet released at the time of this writing</del><a href="http://devhell.info/post/2015-06-05/talmudic-maxims-for-the-unwashed-masses-phptek-2015/">available here</a>), Chris and Ed discussed <em>soft skills</em> talks with Yitzchok Willroth (<a href="https://twitter.com/coderabbi">@coderabbi</a>). <a href="http://en.wikipedia.org/wiki/Soft_skills">Soft skills</a> are those skills that aren’t necessarily technical in nature—things like interpersonal communication, time management, managing teams, leadership, etc. They’re critical to our jobs, but we often see them as secondary to our technical skills. In fact, they are not soft at all—they’re rather difficult to master, which is why it’s important that we talk about them at conferences and write about them on our blogs and in our trade journals.</p>
<p>At the podcast, I tried to elucidate a sentiment that’s been on my mind for some time, but it came out as rambling nonsense. I’m sorry. Here’s what I was trying to get at.</p>
<p><span class="pullquote-right " data-pullquote="I assumed the next step for a seasoned speaker should be to start positioning myself for keynote opportunities."></span>
I’ve been a conference speaker for many years. For a few recent years, I ramped down my speaking and took some time off from conferences to focus on my work, and as I started to ramp things back up, I tried to assess my options and how I wanted to position myself. I assumed the next step for a seasoned speaker should be to start positioning myself for keynote opportunities.</p>
<p>I’ve always given very technical talks, and I’ve observed that keynotes are usually non-technical and focused on ideas, concepts, and soft skills, usually filled with personal anecdotes and inspirational stories. So, I set out to craft some talks that would help take me on a new direction in my speaking career.</p>
<p>In 2013, I made my comeback appearance at CoderFaire Atlanta, where I was invited to give the conference keynote. This was supposed to be my shining moment as a keynote speaker to elaborate on the “<a href="https://benramsey.com/articles/debugging-zen/">Debugging Zen</a>” article I had written for <em>Web Advent</em>. The keynote was entitled “<a href="https://benramsey.com/talks/2013/04/coderfaire-developing-intuition/">Developing Intuition: How to Think Like a Software Architect</a>.” I shifted the focus away from debugging and told my story of how I came to be a software developer and the heavy role intuition has played in my career. I think the talk resonated for about half of the audience. The other half probably thought it was a bunch of hokey gibberish.</p>
<p>I spoke at php[tek] a little later that year, after having taken three years off from speaking there. I gave a presentation entitled “<a href="https://benramsey.com/talks/2013/05/phptek-api-first/">API First</a>.” This was another soft talk (with a little bit of technical detail thrown in), building on my experiences developing and deploying APIs. In it, I talked about how to approach your managers and company leadership to convince them of taking an API-first approach to web application development. It was well-received and I saw a lot of great feedback, but it was not easy to prepare. <a href="https://benramsey.com/talks/2013/10/zendcon-api-first/">I gave it again at ZendCon</a> later that year. Again, I received high marks and good feedback, but it felt lacking in a certain kind of energy and levity. After the intuition talk at CoderFaire, I realized that I’m not good at telling stories or relating anecdotes, and that was evident here, as well.</p>
<p>That same year, <a href="http://eliw.com/">Eli</a> asked me to put together the closing talk for php[architect]’s PHP 5.5 Web Summit. He wanted me to talk about <a href="https://benramsey.com/talks/2013/09/phparch-modern-php/">modern PHP development</a>, so I decided to turn it into an observation of how best practices have arisen in the community over the years. I gave the talk many times over the following year, but it always had mixed reviews. On one side were the community <em>old-timers</em> with whom the historical look-back resonated. On the other hand were folks newer to the community who criticized the talk as a bunch of nostalgic navel-gazing and were expecting a different kind of talk.</p>
<p>I made one more attempt at a soft talk. Again, I refined my “Debugging Zen” article into <a href="https://benramsey.com/talks/2014/09/madisonphp-debugging-zen/">its own talk</a>, discussing the role intuition plays for me in the art of debugging and how others can tap into their own intuition to be better software developers. At the Madison PHP Conference, where I first presented it, I gave it to a crowded room and received many encouraging comments. However, each time I’ve given the talk since, I’ve heard mixed feedback and even negative comments.</p>
<p><span class="pullquote-left " data-pullquote="I’m a very introspective person, which I think works well in written form but falls flat for me in spoken form."></span>
I’m a very introspective person, which I think works well in written form but falls flat for me in spoken form. So, I’ve decided to retire these talks. I still feel they are important, but I’m not the best person to deliver them.</p>
<p>Now, back to the Development Hell podcast recording. Chris, Ed, and Yitz were discussing soft talks and it seemed to me the general sentiment was that all speakers should submit both soft skills and technical skills talks to tech conferences, and especially if you’re going to present a keynote, it needs to be heavily slanted to the soft side. Is this true?</p>
<p>At php[tek] this past week, I introduced two brand-new technical talks. I had a blast preparing and delivering them, and I felt they were among the best talks I’ve given in the last three years, so maybe I’ve finally hit my stride and found myself again as a speaker, after attempting for so long to go in a direction that doesn’t suit me well. I’ll spend a few more years honing my abilities as a technical speaker, and in the future, maybe I’ll be ready to work hard on practicing and delivering another soft talk.</p>
<p>Should every technical speaker have a soft talk included in their toolbox of talks? What about those who are much better at teaching technical skills than they are at motivating behavior? Is it possible to have a mostly technical keynote, or must keynotes always be soft? Observationally, it seems to me that PHP conferences used to be heavily technical and now they’re a mix of technical and life/professional skills talks. Is the mix just right, or is it skewed too much one way or the other?</p>
<p><em><a rel="author" href="http://benramsey.com">Ben Ramsey</a> is a web developer, author, and speaker. He is a software architect at <a href="https://www.shootproof.com">ShootProof</a>, where he builds a platform for professional photographers. He enjoys organizing user groups and contributing to open source software. Ben blogs at <a href="http://benramsey.com">benramsey.com</a> and is <a href="https://twitter.com/ramsey">@ramsey</a> on Twitter.</em></p>
<p><small><em>“My Failed Attempts at Soft Skills Talks” was originally published at <a rel='bookmark' href='https://benramsey.com/blog/2015/05/my-failed-attempts-at-soft-skills-talks/'>benramsey.com</a> and is Copyright © 2015 Ben Ramsey. It is licensed for use under a <a rel='license' type='text/html' href='http://creativecommons.org/licenses/by-sa/4.0/'>Creative Commons Attribution-ShareAlike license</a>.</em></small></p>
Learning A New Codebase
2014-09-17T22:30:00+00:00
http://benramsey.com/blog/2014/09/learning-a-new-codebase
Copyright © 2014 Ben Ramsey.
What can developers do during the interview process to get an idea of the kind of codebase a company has? Here are a few tips I think go a long way in helping determine the state of a company's codebase.
<p><img width="100%" src="https://files.benramsey.com/ws/blog/2014-09-17-learning-a-new-codebase/banner-1500x630.jpg"></p>
<p>A few days ago, my friend <a href="http://funkatron.com/">Ed Finkler</a> started a <a href="https://twitter.com/funkatron/status/507523737759932416">new job</a>. Earlier this week, he posted on Twitter:</p>
<div class="embed rich Twitter"><blockquote class="twitter-tweet"><p lang="en" dir="ltr">First days humble us all.</p>— Ed Finkler (@funkatron) <a href="https://twitter.com/funkatron/status/511689325398863872?ref_src=twsrc%5Etfw">September 16, 2014</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<p>Having begun <a href="http://benramsey.com/blog/2014/08/my-first-month-at-shootproof/">a new job myself</a>, I shared Ed’s sentiment. Last weekend, while at the <a href="http://2014.madisonphpconference.com/">Madison PHP Conference</a>, we were discussing what developers can do during the interview process to get an idea of the kind of codebase a company has. After all, the developer is interviewing potential employers just as much as they are being interviewed as a potential employee. It would suck to be hired only to find the code is in shambles. Short of signing an NDA and asking to see the their code, what can you do?</p>
<p>Here are a few tips I think go a long way in helping determine the state of a company’s codebase. If you have other ideas, feel free to leave them in the comments.</p>
<ol>
<li>
<p><em>Ask what coding standards the company follows.</em> Can they articulate those standards well? Grill them on specifics. Be sure to ask this of the developers and not the managers. Otherwise, you might not get a good picture of how standards factor into their practices.</p>
<p>For PHP projects, you should hear something about <a href="http://www.php-fig.org/psr/psr-2/">PSR-2</a> and <a href="http://www.php-fig.org/psr/psr-1/">PSR-1</a>. If not, then at least the old <a href="http://pear.php.net/manual/en/standards.php">PEAR coding standards</a> should come up.</p>
</li>
<li>
<p><em>Ask whether the company uses a dependency/package management tool.</em> Answers to this question are a good indication of whether the company subscribes to a <a href="http://en.wikipedia.org/wiki/Not_invented_here">not invented here (NIH)</a> philosophy. Companies that reuse code from a variety of third-party packages tend to—in my experience—have better structured and cleaner codebases. I’m not sure why this is, but I suspect it’s because the developers have more exposure to how others are doing things and pick up on best practices in this way.</p>
<p>For PHP projects, you should hear the company talk about their use of <a href="https://getcomposer.org/">Composer</a>. At the very least, they should mention <a href="http://pear.php.net/">PEAR</a>, but <a href="http://benramsey.com/blog/2013/11/the-fall-of-pear-and-the-rise-of-composer/">PEAR is waning</a>.</p>
</li>
<li>
<p><em>Ask how much of the code is covered by tests.</em> There are unit tests, functional tests, integration tests, and acceptance tests. Maybe there are others that I’m not aware of. Start a conversation about which testing strategies the company uses and how many tests they have.</p>
<p>For PHP and web projects, there are many different testing tools available. At the least, I would expect to hear a company talk about <a href="https://phpunit.de/">PHPUnit</a>, but even if they don’t, there are plenty of other unit testing frameworks for PHP, so they may have chosen to use something else. If so, ask why. Questioning a company’s decisions isn’t important, but I think it is enlightening to understand what factors go into their decisions.</p>
</li>
<li>
<p><em>Ask to have the company’s deployment process described.</em> As a developer, will you deploy code, or is that handled by different people/teams? Will you be able to push code on your first day or in your first week? The timing isn’t as important as the processes around deploying, though. Try to get a sense for whether it’s a clean and straightforward process versus a haphazard and error-prone catastrophe.</p>
</li>
</ol>
<p>As a follow-up, after you join a company, you are now faced with the daunting task of learning a new codebase. This morning, Ed asked in the #phpmentoring IRC channel on Freenode:</p>
<figure class="code-highlight-figure"><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="nt"><funkatron> </span>How do you deal with coming in to a huge code base you're not familiar with?</div></div></pre></div></figure>
<p>Here are the two tips I offered from my experiences:</p>
<ol>
<li><em>Go through existing bug reports, fixing bugs.</em> This helps you learn the code base, while feeling productive.</li>
<li><em>Write tests.</em> If they don’t have tests, start a test project and start writing them. Aim for some low percentage of code coverage (i.e. 5-10%) at first. It’ll help you learn the code base quickly.</li>
</ol>
<p>What are your tips for questions to ask potential employers and learning a new codebase once you’ve begun a new job?</p>
<p><em><a rel="author" href="http://benramsey.com">Ben Ramsey</a> is a web developer, author, and speaker. He is a software architect at <a href="https://www.shootproof.com">ShootProof</a>, where he builds a platform for professional photographers. He enjoys organizing user groups and contributing to open source software. Ben blogs at <a href="http://benramsey.com">benramsey.com</a> and is <a href="https://twitter.com/ramsey">@ramsey</a> on Twitter.</em></p>
<p><small><em>“Learning A New Codebase” was originally published at <a rel='bookmark' href='https://benramsey.com/blog/2014/09/learning-a-new-codebase/'>benramsey.com</a> and is Copyright © 2014 Ben Ramsey. It is licensed for use under a <a rel='license' type='text/html' href='http://creativecommons.org/licenses/by-sa/4.0/'>Creative Commons Attribution-ShareAlike license</a>.</em></small></p>
Setting Up Jenkins on Amazon Linux for PHP Testing
2014-08-07T15:45:00+00:00
http://benramsey.com/blog/2014/08/setting-up-jenkins-on-amazon-linux-for-php-testing
Copyright © 2014 Ben Ramsey.
One of my first tasks at ShootProof was to set up a Jenkins server for continuous integration and get it ready to run unit tests for PHP and JavaScript code. There are plenty of tutorials around the web to help you do just that. This is yet another one, but it's primarily my cleaned-up notes—and ...
<p><img width="100%" src="https://files.benramsey.com/ws/blog/2014-08-07-setting-up-jenkins-on-amazon-linux-for-php-testing/banner-1500x630.jpg"></p>
<p>One of my first tasks at <a href="https://www.shootproof.com/">ShootProof</a> was to set up a <a href="http://jenkins-ci.org/">Jenkins</a> server for continuous integration and get it ready to run unit tests for PHP and JavaScript code. There are plenty of tutorials around the web to help you do just that. This is yet another one, but it’s primarily my cleaned-up notes—and less of a tutorial—placed here for my future self to find and provided publicly for all to benefit.</p>
<p>These instructions are specifically tailored for setting up Jenkins on an <a href="http://aws.amazon.com/amazon-linux-ami/">Amazon Linux EC2 instance</a>. If that’s not what you’re running, your mileage may vary. These commands should run on RHEL-based systems, and with modifications to the package manager and names of packages, they should work on other Unix-like systems.</p>
<h3 id="launch-and-prepare-an-ec2-instance">1. Launch and Prepare an EC2 Instance</h3>
<p>The Amazon Linux AMI I used was the latest (at the time) paravirtual, 64-bit, instance store AMI (<a href="https://console.aws.amazon.com/ec2/v2/home?region=us-east-1#LaunchInstanceWizard:ami=ami-ed8e9284">ami-ed8e9284</a>), but <a href="http://aws.amazon.com/amazon-linux-ami/#Amazon_Linux_AMI_IDs">choosing the latest for your region</a> should work just fine. You can use an EBS-backed volume instead and <a href="https://github.com/alestic/ec2-consistent-snapshot">set up regular snapshots</a> of it, or you can follow these directions, <a href="http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/creating-an-ami-instance-store.html">create an AMI</a> from your configured instance, and set up regular snapshots of the EBS volume we attach to the instance. Either way will work fine. I just happened to use an instance store with an EBS volume attached.</p>
<ol>
<li>Launch an EC2 instance (use <a href="https://console.aws.amazon.com/ec2/v2/home?region=us-east-1#LaunchInstanceWizard:ami=ami-ed8e9284">this link</a> to launch one, if you like)</li>
<li><a href="http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-creating-volume.html">Create an EBS volume</a></li>
<li><a href="http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-attaching-volume.html">Attach the EBS volume</a> to the instance you launched</li>
<li>SSH to the instance, format and mount the EBS volume (see below)</li>
</ol>
<p>I’m using <a href="http://en.wikipedia.org/wiki/XFS">XFS</a> for the EBS volume’s file system, but you may use what you prefer. We’ll mount the volume at <code>/var/lib/jenkins</code>, so that we don’t have to do any complex trickery with the default jenkins user, home, and permissions. The EBS volume may exist at <code>/dev/xvdf</code>, as it does in the following example, or it may be attached at another point. See also Amazon’s guide to “<a href="http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-using-volumes.html">Making an Amazon EBS Volume Available for Use</a>.”</p>
<p><em><strong>Note:</strong> All of these instructions require root access. You may prefix them with <code>sudo</code>, or you may change to the root user.</em></p>
<figure class="code-highlight-figure"><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> yum install xfsprogs
</div></div><div data-line="2" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> mkfs -t xfs /dev/xvdf
</div></div><div data-line="3" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> mkdir -p /var/lib/jenkins
</div></div><div data-line="4" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> mount /dev/xvdf /var/lib/jenkins</div></div></pre></div></figure>
<p>Now, the volume is mounted at <code>/var/lib/jenkins</code>. We want to ensure it always gets mounted there when we restart the instance, so let’s add a line to <code>/etc/fstab</code>:</p>
<figure class="code-highlight-figure"><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> cp /etc/fstab /etc/fstab.orig
</div></div><div data-line="2" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> sh -c <span class="s1">'echo "/dev/xvdf /var/lib/jenkins xfs defaults,nofail 0 2" >> /etc/fstab'</span>
</div></div><div data-line="3" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> mount -a</div></div></pre></div></figure>
<h3 id="install-and-start-jenkins">2. Install and Start Jenkins</h3>
<p>Installing and starting Jenkins is fairly simple. We need to add the official Jenkins project repository to the list of yum repos, and then we install with yum, start the service, and ensure that Jenkins starts up on a reboot.</p>
<figure class="code-highlight-figure"><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat-stable/jenkins.repo
</div></div><div data-line="2" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> rpm --import http://pkg.jenkins-ci.org/redhat-stable/jenkins-ci.org.key
</div></div><div data-line="3" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> yum update
</div></div><div data-line="4" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> yum install jenkins
</div></div><div data-line="5" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> service jenkins start
</div></div><div data-line="6" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> chkconfig jenkins on</div></div></pre></div></figure>
<h3 id="configure-the-server-for-running-tests">3. Configure the Server for Running Tests</h3>
<p>Now, we need to install some stuff on the system so that Jenkins can do its thing. These instructions are intended for tests that use the <a href="http://jenkins-php.org">Template for Jenkins Jobs for PHP Projects</a>. This will give you a basic PHP installation with all the tools necessary to run the template. If you need to use anything that deviates from the stock template, then you’ll need to make changes.</p>
<figure class="code-highlight-figure"><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> yum install ant git graphviz gcc gcc-c++
</div></div><div data-line="2" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> yum install php55 php55-devel php55-common php55-cli php55-intl php55-gd php55-pecl-imagick php55-mbstring php55-mcrypt php55-mysqlnd php55-pdo php55-pecl-xdebug
</div></div><div data-line="3" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> sh -c <span class="s1">'sed -i "s/^memory_limit =.*/memory_limit = 256M/" /etc/php.ini'</span>
</div></div><div data-line="4" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> sh -c <span class="s1">'sed -i "s/^;date\.timezone =.*/date\.timezone = America\/New_York/" /etc/php.ini'</span></div></div></pre></div></figure>
<h4 id="nodejs">Node.js</h4>
<p>Since I want to use <a href="http://nodejs.org/">Node.js</a> for various build tools and to run JavaScript tests, I installed Node.js from source (yum always seems to have an outdated package). If you don’t need Node.js, you may skip this.</p>
<figure class="code-highlight-figure"><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> wget http://nodejs.org/dist/v0.10.30/node-v0.10.30.tar.gz
</div></div><div data-line="2" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> tar zxf node-v0.10.30.tar.gz <span class="o">&&</span> <span class="nb">cd </span>node-v0.10.30
</div></div><div data-line="3" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> ./configure
</div></div><div data-line="4" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> make
</div></div><div data-line="5" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> make install
</div></div><div data-line="6" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> ln -s /usr/local/bin/node /usr/bin/node
</div></div><div data-line="7" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> ln -s /usr/local/bin/npm /usr/bin/npm</div></div></pre></div></figure>
<p>See those last two lines where I’m creating symlinks? This is because the jenkins user doesn’t have <code>/usr/local/bin</code> in its <code>PATH</code>. Rather than adjusting the user’s <code>PATH</code>, I chose to create symbolic links in <code>/usr/bin</code>, so that jenkins can find the <code>node</code> and <code>npm</code> programs.</p>
<h4 id="phantomjs-and-casperjs">PhantomJS and CasperJS</h4>
<p>Finally, I also want to install <a href="http://phantomjs.org/">PhantomJS</a> and <a href="http://casperjs.org/">CasperJS</a> to supplement and aid in my JavaScript testing. If you don’t need these, you may skip this.</p>
<figure class="code-highlight-figure"><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> yum install fontconfig freetype libfreetype.so.6 libfontconfig.so.1 libstdc++.so.6
</div></div><div data-line="2" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> wget https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-1.9.7-linux-x86_64.tar.bz2 --no-check-certificate
</div></div><div data-line="3" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> tar jxf phantomjs-1.9.7-linux-x86_64.tar.bz2
</div></div><div data-line="4" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> cp phantomjs-1.9.7-linux-x86_64/bin/phantomjs /usr/local/bin/phantomjs
</div></div><div data-line="5" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> npm install -g casperjs
</div></div><div data-line="6" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> ln -s /usr/local/bin/phantomjs /usr/bin/phantomjs
</div></div><div data-line="7" class="code-highlight-row unnumbered"><div class="code-highlight-line"><span class="gp">$</span> ln -s /usr/local/bin/casperjs /usr/bin/casperjs</div></div></pre></div></figure>
<p>Notice the symbolic links created in the last two lines again. This is for the same reason I mentioned earlier: to help the jenkins user find these programs in its <code>PATH</code>.</p>
<h3 id="configure-jenkins">4. Configure Jenkins</h3>
<p>Now, we’ve got Jenkins running, and the server has been configured to run our tests. You can go to Jenkins in a web browser to do the rest. By default, Jenkins runs on port 8080, so you can go to http://ec2-x-x-x-x.compute-1.amazonaws.com:8080/ to set it up.</p>
<p>The first thing you’ll want to do is enable security. I prefer to install the <a href="https://wiki.jenkins-ci.org/display/JENKINS/Github+OAuth+Plugin">GitHub OAuth Plugin</a> and use GitHub to authenticate with Jenkins. I would also recommend setting up a proxy to Jenkins through Apache or Nginx and installing an SSL certificate to encrypt your communications with Jenkins. You might also consider using AWS security groups to restrict access to Jenkins by IP addresses. All of these are outside the scope of this post.</p>
<ol>
<li><a href="http://jenkins-php.org/installation.html">Install the Jenkins plugins required by the Template for Jenkins Jobs for PHP Projects</a>. You’ll also need to install the required PHP tools listed on that page, or you may choose to use <a href="https://github.com/ramsey/jenkins-php">my jenkins-php meta-package</a> with Composer to install them for you when you run Jenkins builds. If you choose the latter, be sure to set up your Ant build.xml script to also run <code>composer install</code> on each build during the “prepare” stage and point the executable for each tool to the <code>vendor/bin/</code> directory (where Composer installs them).</li>
<li>Create the <a href="http://jenkins-php.org/automation.html">Ant build.xml</a> script for your project.</li>
<li><a href="http://jenkins-php.org/integration.html">Install the job template for PHP jobs</a> and set up your first job using the template.</li>
</ol>
<p>Here are a few other plugins that might come in handy:</p>
<ul>
<li><strong>GitHub Plugin:</strong> this plugin allows you to configure a job to pull source from a GitHub project, and you can set up GitHub web hooks to trigger builds on each code push to the repo</li>
<li><strong>GitHub pull request builder plugin:</strong> this plugin will allow you to trigger a build on a pull request</li>
<li><strong>HipChat Plugin / IRC Plugin / Slack Notification Plugin:</strong> these plugins allow you to configure a job to send messages to channels on your favorite team chat servers</li>
</ul>
<p><em><a rel="author" href="http://benramsey.com">Ben Ramsey</a> is a web developer, author, and speaker. He is a software architect at <a href="https://www.shootproof.com">ShootProof</a>, where he builds a platform for professional photographers. He enjoys organizing user groups and contributing to open source software. Ben blogs at <a href="http://benramsey.com">benramsey.com</a> and is <a href="https://twitter.com/ramsey">@ramsey</a> on Twitter.</em></p>
<p><small><em>“Setting Up Jenkins on Amazon Linux for PHP Testing” was originally published at <a rel='bookmark' href='https://benramsey.com/blog/2014/08/setting-up-jenkins-on-amazon-linux-for-php-testing/'>benramsey.com</a> and is Copyright © 2014 Ben Ramsey. It is licensed for use under a <a rel='license' type='text/html' href='http://creativecommons.org/licenses/by-sa/4.0/'>Creative Commons Attribution-ShareAlike license</a>.</em></small></p>
My First Month at ShootProof
2014-08-04T03:00:00+00:00
http://benramsey.com/blog/2014/08/my-first-month-at-shootproof
Copyright © 2014 Ben Ramsey.
My first day at ShootProof was July 1st, and as I've come to my one-month anniversary with the company, I wanted to share some of the reasons that attracted me to ShootProof and why I'm still excited about it, after a month of working here.
<p><img width="100%" src="https://files.benramsey.com/ws/blog/2014-08-01-my-first-month-at-shootproof/banner-1500x630.jpg"></p>
<p>It’s difficult to write a blog post about a new gig without coming across as sounding critical of past employers. That’s not my intent, but this first month I’ve spent at <a href="https://www.shootproof.com/">ShootProof</a> has been one of the best months I’ve had in a long time, career-wise.</p>
<p>My first day at ShootProof was July 1st, and as I’ve come to my one-month anniversary with the company, I wanted to share some of the reasons that attracted me to ShootProof and why I’m still excited about it, after a month of working here.</p>
<h3 id="the-team">The Team</h3>
<p>The primary reason I joined ShootProof was for the team. I had worked with <a href="http://www.robertswarthout.com/">Robert Swarthout</a> and <a href="http://www.deshong.net/">Brian DeShong</a> previously at Schematic (now <a href="http://www.possible.com/">POSSIBLE</a>). We worked well together then, and the opportunity to work with them again was almost too good to be true. On top of that, ShootProof hires the best. With folks like <a href="http://www.beparticular.com/">Jenn Downs</a>, <a href="https://twitter.com/Artifacture">Terry Allen</a>, <a href="https://twitter.com/iambandy">Kevin Bandy</a>, <a href="http://byjad.com/">Josh Davies</a>, <a href="https://twitter.com/neighbor">Colin Breece</a>, and the rest of the ShootProof team, ShootProof really is a dream team.</p>
<p>At PHP Tek 2009, my friend <a href="http://seancoates.com/">Sean Coates</a> gave me some awesome career advice. He said, “You need to work with people who know you.” At ShootProof, I am doing just that, and it’s a great working relationship.</p>
<h3 id="bootstrapped">Bootstrapped</h3>
<p>Another thing that attracted me to ShootProof is its funding. As of today, it’s 100% bootstrapped. Ideologically, I’m not one of those who say your company must be bootstrapped or VC funded. There are pros and cons to both types of funding. But having experienced VC funding, a bootstrapped company had a certain appeal to me: all the investors have “skin in the game” in both the monetary investment sense, as well as the <em><a href="http://www.implementingscrum.com/2006/09/11/the-classic-story-of-the-pig-and-chicken/">agile “pig”</a></em> sense.</p>
<p>What this means for me is that I work on a daily basis with the primary decision makers in the company, and these decision makers answer only to themselves (and our customers). There’s a great deal of freedom and trust in this relationship.</p>
<p>Will we always remain bootstrapped? That’s not a question for me to answer or even to presume to know the answer. There are a variety of reasons we may or may not consider funding in the future, and that’s a question for our founders to tackle, but for now, the fact that we’re bootstrapped is important to me. It all comes back to the team. We’re intimate. We’re lean. We’re agile. We’re not tied down by VC money. We work only for our customers and ourselves.</p>
<h3 id="top-notch-support-team">Top-notch Support Team</h3>
<p>After meeting with Colin, I realized that ShootProof not only prides itself in building a great product, but our <em>special sauce</em> is our customer support team. Our loyalty builders will do whatever it takes to ensure the happiness of our customers. I know this makes me sound rather dense and naïve, having worked in the industry for so many years, but after hearing about the work of our customer support team, I realized that customer support is just as much a part of our product as the code that makes up our web properties. I’m proud of the work they do, and I’m excited to be a part of their team.</p>
<h3 id="user-experience">User Experience</h3>
<p>Along with customer support, ShootProof is working to ensure we have the best possible user experience for our customers. That’s why we have ace UX folks on our team.</p>
<p>User experience has always been an important cornerstone of software development to me. How users feel when they interact with your software interface determines whether they want to continue using it or not. Working at Schematic showed me how UX must be a discipline to any software company. I am more than thrilled that ShootProof feels the same way and has made it a crucial tenet of our process.</p>
<h3 id="product">Product</h3>
<p>As Brian said in his <a href="http://www.deshong.net/blog/2014/7/joining-shootproof">“Joining ShootProof” blog post</a>, I also sought out ShootProof because I love to build products. I want to work for a company that is product-focused. Not only is ShootProof product-focused, they know their customer so well that they have been able to hone in on exactly what product to build for those customers. In fact, many of our team members are professional photographers themselves. That expertise and specificity is another reason I was attracted to ShootProof.</p>
<h3 id="revenue">Revenue</h3>
<p>ShootProof is a startup and a bootstrapped start-up at that. While I said earlier that the bootstrapped nature of the company attracted me, I would be lying if I said that revenue was not important. Many times, we hear “bootstrapped startup” and assume this means the company is not making any money. That is not the case with ShootProof. I can’t share numbers, but I can say that year-over-year growth has been sizable.</p>
<h3 id="culture">Culture</h3>
<p>I’m not interested in joining a fly-by-night startup whose desire is to jump into a market, disrupt it, and get out quickly, making tons of money. Those get-rich schemes rarely succeed and don’t appeal to me. Money is nice, but not at the expense of my family, health, and relationships. ShootProof is a company with focus, a clear direction, and respect for its team members.</p>
<p>Recently, <a href="http://blog.calevans.com/">Cal Evans</a> wrote a blog post entitled, “<a href="http://blog.calevans.com/2014/07/30/its-all-about-culture/">It’s All About Culture</a>.” In it, he wrote:</p>
<blockquote>
<p>The bedrock of a good developer culture is respect. Respect for the fact that
you have developers to build things on which the company is based. Respect
for the fact that without developers, the company most likely would not
exist. Culture is not putting developers on a pedestal and offering them
trinkets as tribute. Culture is understanding that developers aren’t cogs in
a machine that can be replaced on a whim.</p>
</blockquote>
<p>Culture is one of those things that’s difficult to define and hard to articulate, but I think Cal hits the nail on the head here. A good culture focuses on the people who make up the team. ShootProof’s culture is one of respect for each other. The focus is on people. One of the things Robert said to me when we were first discussing the possibility of me joining ShootProof is that he wants to build a first-class team that makes others say to themselves, “That’s a great team! I want to work with that team, too.”</p>
<p>The people and the focus on the people are what attracted me to ShootProof, and that’s why I’m still excited about ShootProof a month after joining them.</p>
<p><em><a rel="author" href="http://benramsey.com">Ben Ramsey</a> is a web developer, author, and speaker. He is a software architect at <a href="https://www.shootproof.com">ShootProof</a>, where he builds a platform for professional photographers. He enjoys organizing user groups and contributing to open source software. Ben blogs at <a href="http://benramsey.com">benramsey.com</a> and is <a href="https://twitter.com/ramsey">@ramsey</a> on Twitter.</em></p>
<p><small><em>“My First Month at ShootProof” was originally published at <a rel='bookmark' href='https://benramsey.com/blog/2014/08/my-first-month-at-shootproof/'>benramsey.com</a> and is Copyright © 2014 Ben Ramsey. It is licensed for use under a <a rel='license' type='text/html' href='http://creativecommons.org/licenses/by-sa/4.0/'>Creative Commons Attribution-ShareAlike license</a>.</em></small></p>