<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://ben.ramsey.dev/feeds/blog.atom</id>
  <updated>2026-05-31T15:10:52+00:00</updated>
  <title type="text">Ben Ramsey</title>
  <subtitle type="text">Coder, Author, &amp; Speaker</subtitle>
  <author>
    <name>Ben Ramsey</name>
    <uri>https://ben.ramsey.dev/</uri>
    <email>ben@ramsey.dev</email>
  </author>
  <rights type="html">Copyright © Ben Ramsey. Licensed for use under &lt;a href="https://creativecommons.org/licenses/by-sa/4.0/"&gt;CC BY-SA&lt;/a&gt;.</rights>
  <link rel="self" type="text/xml" href="https://ben.ramsey.dev/feeds/blog.xml"/>
  <link rel="canonical" type="application/atom+xml" href="https://ben.ramsey.dev/feeds/blog.atom"/>
  <link rel="alternate" type="application/rss+xml" href="https://ben.ramsey.dev/feeds/blog.rss"/>
  <link rel="alternate" type="text/html" href="https://ben.ramsey.dev/blog"/>
  <link rel="license" type="text/html" href="https://creativecommons.org/licenses/by-sa/4.0/"/>
  <link rel="license" type="application/rdf+xml" href="https://creativecommons.org/licenses/by-sa/4.0/rdf"/>
  <category term="technology" label="Technology"/>
  <category term="web-development" label="Web Development"/>
  <category term="software-engineering" label="Software Engineering"/>
  <category term="php" label="Programming Languages: PHP"/>
  <entry>
    <title type="text">Generating HTTPS URLs with Symfony on DigitalOcean App Platform</title>
    <link rel="alternate" type="text/html" href="https://ben.ramsey.dev/blog/2026/05/https-urls-with-symfony-on-digitalocean"/>
    <published>2026-05-31T15:10:52+00:00</published>
    <updated>2026-05-31T15:10:52+00:00</updated>
    <id>urn:uuid:019e7e96-7c60-73f1-b6ae-8524cdda5ce9</id>
    <author>
      <name>Ben Ramsey</name>
      <email>ben@ramsey.dev</email>
    </author>
    <content type="html">&lt;p&gt;I’ve been dealing with a frustrating issue in a &lt;a href="https://symfony.com"&gt;Symfony&lt;/a&gt; application hosted on &lt;a href="https://docs.digitalocean.com/products/app-platform/"&gt;DigitalOcean App Platform&lt;/a&gt;. Since it took me quite a while to find the solution, I thought I’d share it here in case it helps someone else.&lt;/p&gt;
&lt;p&gt;By default, every application running on App Platform includes &lt;a href="https://developers.cloudflare.com/cache/"&gt;Cloudflare CDN&lt;/a&gt; as a reverse proxy. This provides a number of benefits, especially if your application sets appropriate &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control"&gt;&lt;code&gt;cache-control&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/ETag"&gt;&lt;code&gt;etag&lt;/code&gt;&lt;/a&gt; headers. Cloudflare will use these to cache your application’s responses at &lt;a href="https://deno.com/blog/the-future-of-web-is-on-the-edge"&gt;&lt;em&gt;the edge&lt;/em&gt;&lt;/a&gt;, thus reducing load on your servers. So far, so good.&lt;/p&gt;
&lt;p&gt;Cloudflare also terminates TLS, which means the traffic is decrypted before being forwarded to DigitalOcean. This presents a problem for my application. It thinks it’s receiving traffic over HTTP rather than HTTPS. As a result, Symfony generates URLs with the &lt;code&gt;http://&lt;/code&gt; scheme rather than &lt;code&gt;https://&lt;/code&gt;. This isn’t a major problem, since everything is configured to redirect to &lt;code&gt;https://&lt;/code&gt;, but it requires an additional network request, and it’s one of those tiny details that will bother me until I figure out how to fix it.&lt;/p&gt;
&lt;blockquote class="pullquote"&gt;
&lt;p&gt;It’s one of those tiny details that will bother me until I figure out how to fix it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Meanwhile, Symfony’s documentation isn’t clear about how to solve this. Three pages came up in my search for a solution:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://symfony.com/doc/current/security/force_https.html"&gt;How to Force HTTPS or HTTP for different URLs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://symfony.com/doc/current/routing.html#routing-force-https"&gt;Routing: Forcing HTTPS on Generated URLs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://symfony.com/doc/current/deployment/proxies.html"&gt;How to Configure Symfony to Work behind a Load Balancer or Reverse Proxy&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The first isn’t relevant to my problem. It’s about forcing HTTPS or HTTP for different URLs, not about generating HTTPS URLs when behind a reverse proxy. Plus, it has this scary warning at the bottom of the page:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Forcing HTTPS while using a reverse proxy or load balancer requires a proper configuration to avoid infinite redirect loops.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The second one indicates it’s for use when generating URLs in non-HTTP requests (e.g., from CLI tools, cron jobs, email sending tasks, etc.). It also includes the same scary warning:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If your server runs behind a proxy that terminates SSL, make sure to &lt;a href="https://symfony.com/doc/current/deployment/proxies.html"&gt;configure Symfony to work behind a proxy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The configuration for the scheme is only used for non-HTTP requests. The schemes option together with incorrect proxy configuration will lead to a redirect loop.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That warning also links to the third page, which &lt;em&gt;is&lt;/em&gt; relevant to my problem. However, anything involving network configuration and &lt;a href="https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing"&gt;CIDR notation&lt;/a&gt; has always intimidated me. I was afraid of breaking connectivity to the application, and the only way I could find out whether it worked was to try it in production.&lt;/p&gt;
&lt;p&gt;In the end, I needed to make two small changes to my application, neither of which are explicitly documented anywhere:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;I replaced &lt;code&gt;x-forwarded-for&lt;/code&gt; with the value of &lt;code&gt;do-connecting-ip&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://docs.digitalocean.com/support/where-can-i-find-the-client-ip-address-of-a-request-connecting-to-my-app/"&gt;note on using &lt;code&gt;do-connecting-ip&lt;/code&gt; instead of &lt;code&gt;x-forwarded-for&lt;/code&gt;&lt;/a&gt; is buried deep in the DigitalOcean documentation, and if you’ve never encountered it, it can come as a surprise. I’ve been around long enough to know this is a common thing that reverse proxies do, so I knew what to look for.&lt;/p&gt;
&lt;p&gt;For Symfony to find the client’s correct IP address, you need to rewrite this header early in the request lifecycle. I did this by adding the following to my &lt;code&gt;index.php&lt;/code&gt; above where the Symfony kernel is instantiated:&lt;/p&gt;
&lt;div class="code-block" data-lang="php"&gt;&lt;pre&gt;&lt;code class="language-php"&gt;// Map DigitalOcean's custom IP header to the standard x-forwarded-for header.
if (isset($_SERVER['HTTP_DO_CONNECTING_IP'])) {
    $_SERVER['HTTP_X_FORWARDED_FOR'] = $_SERVER['HTTP_DO_CONNECTING_IP'];
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I only knew to do this because Symfony &lt;a href="https://symfony.com/doc/current/deployment/proxies.html#custom-headers-when-using-a-reverse-proxy"&gt;shows an example&lt;/a&gt; with a different &lt;code&gt;x-forwarded-*&lt;/code&gt; header.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I added the following to my &lt;code&gt;config/packages/framework.yaml&lt;/code&gt; file:&lt;/p&gt;
&lt;div class="code-block" data-lang="yaml"&gt;&lt;pre&gt;&lt;code class="language-yaml"&gt;framework:
  trusted_proxies: '127.0.0.1,100.64.0.0/10'
  trusted_headers: ['x-forwarded-for', 'x-forwarded-host', 'x-forwarded-proto', 'x-forwarded-port']
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What’s important to note here is the value &lt;code&gt;100.64.0.0/10&lt;/code&gt; in the list of trusted proxies. I could have used &lt;code&gt;REMOTE_ADDR&lt;/code&gt; as suggested in the documentation, but that felt insecure. I tried using &lt;code&gt;PRIVATE_SUBNETS&lt;/code&gt;, also suggested in the documentation, but DigitalOcean uses a subnet not found in &lt;a href="https://github.com/symfony/symfony/blob/32389e2808f35532b9d8691e3624dffce92ee3a3/src/Symfony/Component/HttpFoundation/IpUtils.php#L21-L39"&gt;Symfony’s list of private subnets&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What’s more, I couldn’t find this subnet listed in the DigitalOcean documentation. However, it’s defined in &lt;a href="https://www.rfc-editor.org/info/rfc6598/"&gt;RFC 6598&lt;/a&gt; as the reserved IPv4 prefix for Shared Address Space. I stumbled on it when I noticed the &lt;code&gt;REMOTE_ADDR&lt;/code&gt; value on requests to my application began with &lt;code&gt;100.127&lt;/code&gt;, which wasn’t in Symfony’s list. So I searched to find whether it had any special meaning, and sure enough, it does.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;After making these changes, &lt;code&gt;$request-&amp;gt;getClientIp()&lt;/code&gt; now returns the correct client IP address instead of the IP address of the ingress proxy. I no longer need to use &lt;code&gt;$request-&amp;gt;getHeaders()-&amp;gt;get('do-connecting-ip')&lt;/code&gt; for that value. I am also able to use &lt;code&gt;{{ url('home') }}&lt;/code&gt; in my Twig templates instead of the hacky and ugly &lt;code&gt;https://{{ url('home', {}, true) }}&lt;/code&gt; I was using before.&lt;/p&gt;
</content>
    <category term="php"/>
    <category term="digitalocean"/>
    <category term="symfony"/>
    <rights type="html">Copyright © 2026 Ben Ramsey. Licensed for use under &lt;a href="https://creativecommons.org/licenses/by-sa/4.0/"&gt;CC BY-SA&lt;/a&gt;.</rights>
  </entry>
  <entry>
    <title type="text">PHP Tek: A Homecoming</title>
    <link rel="alternate" type="text/html" href="https://ben.ramsey.dev/blog/2026/05/php-tek-homecoming"/>
    <published>2026-05-24T04:16:00+00:00</published>
    <updated>2026-05-24T04:16:00+00:00</updated>
    <id>urn:uuid:019e5832-6c00-710a-9754-d99154c38da4</id>
    <author>
      <name>Ben Ramsey</name>
      <email>ben@ramsey.dev</email>
    </author>
    <content type="html">&lt;p&gt;PHP Tek always feels like a homecoming. No matter how much time passes between conferences, or between the person I was the last time I attended and the one I am now, walking into that hotel and finding familiar faces feels like returning home to close friends and family. That feeling was especially pronounced in 2023, when the conference returned after a four-year hiatus imposed by the pandemic. This week in Rosemont, back at the Sheraton O’Hare, it was there again.&lt;/p&gt;
&lt;p&gt;The conference ran May 19th through the 21st. It was three days of sessions, workshops, and the kind of hallway conversations that don’t appear on any schedule. I gave two talks: one on &lt;a href="https://ben.ramsey.dev/talks/2026/05/php-tek-openapi"&gt;describing APIs with OpenAPI&lt;/a&gt; on Wednesday, and &lt;a href="https://ben.ramsey.dev/talks/2026/05/php-tek-oauth-oidc"&gt;a beginner’s guide to OAuth and OpenID Connect&lt;/a&gt; on Thursday. Both went well, and I’m always glad for an audience willing to spend an hour in the weeds with me on less glamorous—but no less fascinating or important—parts of development.&lt;/p&gt;
&lt;p&gt;A few of the talk highlights from the conference, for me, were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://joind.in/event/php-tek-2026/nativephp-2026"&gt;Shane Rosenthal speaking about NativePHP&lt;/a&gt; (check out &lt;a href="https://nativephp.com"&gt;NativePHP&lt;/a&gt;—it’s really cool)&lt;/li&gt;
&lt;li&gt;Sarah Peters’s “&lt;a href="https://joind.in/event/php-tek-2026/from-concert-hall-to-code-review-symphony-to-software"&gt;From Concert Hall to Code Review, Symphony to Software&lt;/a&gt;,” where she played violin interludes between sections of her talk&lt;/li&gt;
&lt;li&gt;James Warmoth III’s “&lt;a href="https://joind.in/event/php-tek-2026/from-classroom-code-to-production-code-bridging-the-gap-between-school-and-the-software-industry#add-comment"&gt;From Classroom Code to Production Code: Bridging the Gap Between School and the Software Industry&lt;/a&gt;”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One of the most memorable parts of PHP Tek is the game night, or after party. Game night is a tradition going back to the earliest PHP Tek conferences. You see, PHP Tek takes place in a hotel by the airport, and there’s little to do nearby. The surrounding area isn’t very walkable, and it takes about an hour to get into Chicago. &lt;em&gt;This is a feature, not a bug.&lt;/em&gt; As a result, everyone sticks around to play games, get to know each other, and have fun.&lt;/p&gt;
&lt;p&gt;One of my favorite game night traditions is karaoke.  This tradition has been quietly accumulating across PHP conferences for twenty years. It started, as best I can recall, in a hotel bar at ZendCon in San Jose in 2006. After a &lt;a href="https://www.flickr.com/photos/helly25/310978202/in/album-72157594396634116/"&gt;pirate-themed after party&lt;/a&gt;, we found ourselves in the hotel bar, where they had a DJ leading karaoke. It was so memorable, they made it a part of the after party at ZendCon 2007. I remember doing karaoke after delivering a keynote at the PHP Experience in São Paulo in 2016, which was surreal (the karaoke, not the keynote). That same year we found a karaoke bar near the hotel at PHP Tek in St. Louis. Along the way, we’ve done karaoke at Lone Star PHP in Dallas, Southeast PHP in Nashville, Longhorn PHP in Austin, Cascadia PHP in Portland, among others. The conferences changed, the cities changed, and somehow karaoke kept appearing.&lt;/p&gt;
&lt;p&gt;At PHP Tek, we’ve evolved beyond hunting for a karaoke venue. Since the conference returned in 2023, we’ve been using the sound system already set up in the ballroom during game night to run our own. It happened again on Wednesday, and I ended up leading a good stretch of it. Nobody assigns this role. It just falls to whoever’s willing to go first. (But really, it’s because I’m the most persistent at begging &lt;a href="https://johncongdon.com"&gt;John&lt;/a&gt; to let me do it.)&lt;/p&gt;
&lt;figure&gt;&lt;p&gt;&lt;img src="https://files.benramsey.com/ws/blog/2026-05-24-php-tek-homecoming/php-tek-2026-karaoke.webp" alt="Conference attendees sing karaoke at PHP Tek" /&gt;&lt;/p&gt;
&lt;figcaption&gt;Nate, Jackie, and Larry sing “What It Sounds Like” from &lt;em&gt;KPop Demon Hunters&lt;/em&gt; at PHP Tek&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Another highlight of PHP Tek is &lt;a href="https://www.catan.com/starfarers"&gt;&lt;em&gt;Catan Starfarers&lt;/em&gt;&lt;/a&gt;. This is the most unhinged version of Catan. I’ve never played, but watching is its own pleasure. &lt;a href="https://gravatar.com/omniadams"&gt;Omni Adams&lt;/a&gt; &lt;a href="https://en.wiktionary.org/wiki/gamemaster"&gt;GMs&lt;/a&gt; a game that’s not supposed to have a game master. The games go late. They’re ginormous. I don’t fully understand how anyone wins, and I suspect that’s part of the appeal. Rumor has it, there are folks who attend just to play &lt;em&gt;Starfarers&lt;/em&gt;.&lt;/p&gt;
&lt;figure&gt;&lt;p&gt;&lt;img src="https://files.benramsey.com/ws/blog/2026-05-24-php-tek-homecoming/php-tek-2026-catan-starfarers.webp" alt="Conference attendees play Catan Starfarers" /&gt;&lt;/p&gt;
&lt;figcaption&gt;Kalen, Daniel, Scott, Nia, Omni, and John play &lt;em&gt;Catan Starfarers&lt;/em&gt; at PHP Tek&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;A meaningful moment of the week, for me, was catching up with &lt;a href="https://github.com/ElizabethN/about_me"&gt;Elizabeth Barron&lt;/a&gt;. Elizabeth has been a fixture in the PHP community for many years, and we go way back; we organized &lt;a href="https://web.archive.org/web/20061011151416/http://www.phpappalachia.org/"&gt;PHP Appalachia&lt;/a&gt; together in 2006. We’d stayed loosely in touch over the years, but I don’t think we’d been in the same room since around 2016. She’s back in a significant way now, having &lt;a href="https://thephp.foundation/blog/2026/02/27/welcoming-elizabeth-barron-new-executive-director/"&gt;joined the PHP Foundation as executive director&lt;/a&gt;. We talked mostly about family, life, and things unrelated to PHP or technology. I love that conferences like PHP Tek provide opportunities to catch up with people you haven’t seen in years without any particular agenda.&lt;/p&gt;
&lt;p&gt;There were conversations with more of an agenda, of course. The hallway track at PHP Tek is where a lot of the real thinking happens, and this year, some of the recurring subjects were: &lt;a href="https://wiki.php.net/rfc/context-managers"&gt;context generators&lt;/a&gt;, &lt;a href="https://thephp.foundation/blog/2026/05/18/announcing-ecosystem-security-team/"&gt;supply-chain security in the PHP ecosystem&lt;/a&gt;, the impact of AI on how we write and think about code, and the longer question of where PHP is heading. I don’t think any of these had tidy conclusions, but they benefit from in-person discussions in ways that mailing list discussions can’t provide.&lt;/p&gt;
&lt;p&gt;PHP Tek has outlasted hype cycles, framework wars, and periodic predictions that PHP was dying, and it keeps coming back. The community keeps showing up. That’s the thing about a homecoming: it only means something if people keep coming home.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;One last thing: &lt;a href="https://wurstcon.com"&gt;WurstCon&lt;/a&gt; returned this year, following the close of the conference. This has become a PHP community tradition. For where two or three are gathered together with hot dogs, there is a WurstCon. This time, WurstCon was at &lt;a href="https://www.winkingdog.com"&gt;the Winking Dog&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;&lt;p&gt;&lt;img src="https://files.benramsey.com/ws/blog/2026-05-24-php-tek-homecoming/php-tek-2026-wurstcon.webp" alt="A crowd of PHP developers pose for a group photo outside the Winking Dog" /&gt;&lt;/p&gt;
&lt;figcaption&gt;The WurstCon conference goers outside the Winking Dog&lt;/figcaption&gt;&lt;/figure&gt;
</content>
    <category term="phptek"/>
    <category term="php"/>
    <category term="community"/>
    <rights type="html">Copyright © 2026 Ben Ramsey. Licensed for use under &lt;a href="https://creativecommons.org/licenses/by-sa/4.0/"&gt;CC BY-SA&lt;/a&gt;.</rights>
  </entry>
  <entry>
    <title type="text">The PHP License, Simplified</title>
    <link rel="alternate" type="text/html" href="https://ben.ramsey.dev/blog/2026/05/the-php-license-simplified"/>
    <published>2026-05-01T00:00:00+00:00</published>
    <updated>2026-05-01T00:00:00+00:00</updated>
    <id>urn:uuid:019de0d5-c800-7143-8d65-819f69689233</id>
    <author>
      <name>Ben Ramsey</name>
      <email>ben@ramsey.dev</email>
    </author>
    <content type="html">&lt;p&gt;I’ve been fascinated with copyright since high school and with open source licensing for most of my career. Yes, I’m a nerd, but I really do find it compelling to think about how humans communicate ideas—through words, songs, photographs, videos, and even code—and claim ownership over these products of the mind. Copyright is how we do that, and licensing is one of the tools we use to share what we create. So, when Matthew Sheahan posted &lt;a href="https://news-web.php.net/php.general/327010"&gt;a question&lt;/a&gt; to the php-general mailing list in early 2020, just as COVID-19 lockdowns were taking hold, it caught my attention.&lt;/p&gt;
&lt;p&gt;Matthew’s team needed to use &lt;a href="https://www.php.net/phpdbg"&gt;phpdbg&lt;/a&gt;, but their organization required &lt;abbr title="Open Source Initiative"&gt;OSI&lt;/abbr&gt;-approved licenses, and “the fact that 3.0 and 3.01 are substantively identical is no use to us at all.” While the PHP website &lt;a href="https://web.archive.org/web/20200430134629/https://www.php.net/license/"&gt;said the PHP License 3.01 was OSI-approved&lt;/a&gt;, the OSI’s own &lt;a href="https://web.archive.org/web/20200429233052/https://opensource.org/licenses/alphabetical"&gt;said otherwise&lt;/a&gt;. Only version 3.0 had been formally approved. 3.01 was a minor version bump, nearly identical to 3.0, but that didn’t matter when company policy required it be listed on the OSI website. Since copyright and licensing is an interest of mine, I figured this was a way I could contribute to the PHP project, so I volunteered. &lt;a href="https://lists.opensource.org/pipermail/license-review_lists.opensource.org/2020-March/004716.html"&gt;I contacted the OSI&lt;/a&gt; to &lt;a href="https://opensource.org/licenses/review-process#:~:text=Request%20for%20approval%20of%20a%20legacy%20license"&gt;request legacy approval&lt;/a&gt; for 3.01, and &lt;a href="https://lists.opensource.org/pipermail/license-review_lists.opensource.org/2020-May/004841.html"&gt;the OSI Board voted to approve it in May 2020&lt;/a&gt;. Problem solved.&lt;/p&gt;
&lt;blockquote class="pullquote"&gt;
&lt;p&gt;I figured this was a way I could contribute to the PHP project, so I volunteered.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;But that planted a seed. Looking closely at the PHP License and the Zend Engine License, I saw two well-intentioned licenses that included increasingly awkward provisions; they were showing their age. The PHP project had been using its own custom license since PHP 3, when Rasmus Lerdorf adapted it from the Apache License, version 1.0, with modifications. The Zend Engine License came along with PHP 4, covering sources in the &lt;code&gt;Zend/&lt;/code&gt; directory. Each license contained conditions specific to their respective custodians—restrictions on using the names “PHP” and “Zend,” an advertising acknowledgment clause, and provisions granting only the PHP Group and Zend Technologies the authority to change the licenses.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;After 25 years of &lt;em&gt;cohabitation&lt;/em&gt; within the same source code repository, [PHP and the Zend Engine] are intertwined in ways in which the Zend Engine can no longer be separated and used as a standalone product. Together, they form the PHP programming language reference implementation.&lt;/p&gt;
&lt;p&gt;— &lt;cite&gt;&lt;a href="https://wiki.php.net/rfc/php_license_update"&gt;PHP License Update RFC&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;These weren’t bad licenses. Most developers, distributors, and companies accepted their &lt;em&gt;intent&lt;/em&gt; and moved on. But gaps between intent and substance have a way of accumulating. The Zend Engine, once imagined as a separable product, had been inextricably bound to PHP for 25 years; the notion that it required its own license had become a historical artifact. Condition 4 of the PHP License—restricting derived products from calling themselves “PHP”—created real ambiguity for Linux distributions like Debian, which patch and redistribute PHP. Neither license was GPL-compatible, and the Zend Engine License had never been OSI-approved. Yet strip away the PHP Group-specific and Zend-specific conditions from both licenses, and what remains is effectively the Modified BSD License, otherwise known as BSD-3-Clause.&lt;/p&gt;
&lt;p&gt;So, &lt;a href="https://www.php.net/license/"&gt;&lt;em&gt;that&lt;/em&gt; is now the PHP License&lt;/a&gt;, version 4, and the Zend Engine License, version 3. Not a custom adaptation. Not a derivative. The actual BSD-3-Clause license, with its &lt;a href="https://spdx.org/licenses/BSD-3-Clause.html"&gt;SPDX identifier&lt;/a&gt;, &lt;a href="https://opensource.org/license/bsd-3-clause"&gt;recognized by the OSI&lt;/a&gt;, &lt;a href="https://directory.fsf.org/wiki/License:BSD-3-Clause"&gt;the FSF&lt;/a&gt;, and every major piece of licensing tooling in use today. It’s &lt;a href="https://www.gnu.org/licenses/license-list.html#ModifiedBSD"&gt;compatible with the GPL&lt;/a&gt;. There are no advertising requirements, no restrictions that only a single organization can invoke, no ambiguity for distributors.&lt;/p&gt;
&lt;p&gt;The rights granted by contributors have not changed. The rights granted to users have not changed. The new licenses are fully compatible with the old ones. This is a simplification and nothing more.&lt;/p&gt;
&lt;aside class="admonition tip" role="note"&gt;
&lt;h6 class="admonition-label"&gt;Tip&lt;/h6&gt;
&lt;p&gt;
Check out &lt;a href="https://wiki.php.net/rfc/php_license_update"&gt;the RFC&lt;/a&gt; itself for a full explanation of the changes, including a detailed history and backstory of the licenses.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Getting here required more than &lt;a href="https://wiki.php.net/rfc/php_license_update"&gt;writing an RFC&lt;/a&gt;. The PHP License gives the PHP Group the authority to change it, which meant tracking down each of the original PHP Group members and getting their written consent. Each approved the proposal. Perforce Software, the successor to Zend Technologies, needed to sign off on the Zend Engine side, as well. They provided a formal letter confirming their full authority and support for the change. I hired an attorney to review the proposal and provide advice on any legal questions that might surface during the discussion period. Speaking of which, I allowed for a six-month community discussion period preceding the vote, which passed unanimously.&lt;/p&gt;
&lt;p&gt;Now, if you’re using software licensed under the PHP License 3.01, clause 5 of that license allows you to use the same software under the new version. If you maintain a PECL extension or any other project licensed under PHP License 3.01, clause 5 of that license allows you to adopt the new version. The same permissive spirit that covered your project before still covers it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Once covered code has been published under a particular version of the license, you may always continue to use it under the terms of that version. You may also choose to use such covered code under the terms of any subsequent version of the license published by the PHP Group.&lt;/p&gt;
&lt;p&gt;— &lt;cite&gt;&lt;a href="https://www.php.net/license/3_01.txt"&gt;The PHP License, version 3.01, clause 5&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If your organization has a policy requiring use of OSI-approved licensed open source software, or if you’ve had to explain away the Zend Engine License’s non-approved status to a compliance review, those conversations are over. And if you’ve simply never thought about this because it didn’t affect you, that’s fine too. It’s worth knowing the licenses exist, they’ve been updated, and PHP’s legal foundations now match the spirit of the language and community.&lt;/p&gt;
&lt;p&gt;There are many people to thank for seeing this through: the members of the PHP internals community who engaged with the RFC over a long discussion period, the members of the &lt;a href="https://www.php.net/credits.php"&gt;PHP Group&lt;/a&gt;—Thies, Stig, Shane, Andi, Rasmus, Sam, Sascha, Zeev, Jim, and Andrei—who each took the time to respond to my messages, Perforce Software—and especially &lt;a href="https://mwop.net"&gt;Matthew Weier O’Phinney&lt;/a&gt; and Sara Kilian—for their support and cooperation, &lt;a href="https://www.greant.com"&gt;Zak Greant&lt;/a&gt;, the &lt;a href="https://lists.debian.org/debian-legal/"&gt;debian-legal&lt;/a&gt; and &lt;a href="https://lists.opensource.org/mailman/listinfo/license-discuss_lists.opensource.org"&gt;OSI license-discuss&lt;/a&gt; mailing lists, the &lt;a href="https://www.fsf.org/licensing/"&gt;FSF Licensing &amp;amp; Compliance Team&lt;/a&gt;, and Pamela Chestek of &lt;a href="https://www.chesteklegal.com"&gt;Chestek Legal&lt;/a&gt;. Open source licensing is unglamorous, but it matters, and I’m glad to have had a part in this.&lt;/p&gt;
&lt;aside class="admonition warning" role="note"&gt;
&lt;h6 class="admonition-label"&gt;Caution&lt;/h6&gt;
&lt;p&gt;
Nothing in this post is legal advice. I am not a lawyer. Please consult a lawyer before making any legal decisions.&lt;/p&gt;
&lt;/aside&gt;
</content>
    <category term="php"/>
    <category term="open-source"/>
    <category term="licensing"/>
    <rights type="html">Copyright © 2026 Ben Ramsey. Licensed for use under &lt;a href="https://creativecommons.org/licenses/by-sa/4.0/"&gt;CC BY-SA&lt;/a&gt;.</rights>
  </entry>
  <entry>
    <title type="text">Testing the PDO_ODBC driver on macOS</title>
    <link rel="alternate" type="text/html" href="https://ben.ramsey.dev/blog/2021/05/testing-pdo-odbc-on-macos"/>
    <published>2021-05-12T23:27:23+00:00</published>
    <updated>2021-05-12T23:27:23+00:00</updated>
    <id>urn:uuid:017962e8-0378-727b-826f-e32a4534146a</id>
    <author>
      <name>Ben Ramsey</name>
      <email>ben@ramsey.dev</email>
    </author>
    <content type="html">&lt;aside class="admonition note" role="note"&gt;
&lt;h6 class="admonition-label"&gt;Note&lt;/h6&gt;
&lt;p&gt;
This post was originally published on &lt;a href="https://dev.to/ramsey/testing-the-pdoodbc-driver-on-macos-55n1"&gt;DEV&lt;/a&gt;.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;In response to &lt;a href="https://github.com/cmb69"&gt;Christoph’s&lt;/a&gt; &lt;a href="https://github.com/php/php-src/pull/6935#issuecomment-834270441"&gt;comment on PR #6935&lt;/a&gt;, I wanted to check to see exactly what PHP returns when calling &lt;code&gt;PDO::getAttribute()&lt;/code&gt; on &lt;code&gt;PDO_ODBC&lt;/code&gt; with &lt;code&gt;PDO::ATTR_SERVER_INFO&lt;/code&gt; and &lt;code&gt;PDO::ATTR_SERVER_VERSION&lt;/code&gt;.  &lt;a href="https://github.com/php/php-src/blob/01b3fc03c30c6cb85038250bb5640be3a09c6a32/ext/pdo_odbc/odbc_driver.c#L356-L372"&gt;Looking at the code&lt;/a&gt;, I could tell that it breaks and returns a &lt;code&gt;0&lt;/code&gt;.  I wasn’t sure how it reacted beyond that, and I wanted to test it in PHP to see what would happen.&lt;/p&gt;
&lt;p&gt;To do this, I needed to be able to connect to a database using ODBC on macOS. Since I primarily use MySQL or PostgreSQL, I haven’t used ODBC to connect to a database in almost 20 years.&lt;/p&gt;
&lt;p&gt;My PHP build already had &lt;code&gt;PDO_ODBC&lt;/code&gt; installed, so I didn’t need to rebuild it.&lt;/p&gt;
&lt;div class="code-block" data-lang="shell"&gt;&lt;pre&gt;&lt;code class="language-shell"&gt;$ php -m | grep -i odbc
odbc
PDO_ODBC
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next, I checked to see whether &lt;a href="http://www.unixodbc.org"&gt;unixODBC&lt;/a&gt; was installed, and I wanted to connect to a &lt;a href="https://mariadb.com"&gt;MariaDB&lt;/a&gt; server, so I installed the &lt;code&gt;unixodbc&lt;/code&gt; and &lt;code&gt;mariadb-connector-odbc&lt;/code&gt; packages with &lt;a href="https://brew.sh"&gt;Homebrew&lt;/a&gt;. (It turned out that &lt;code&gt;unixodbc&lt;/code&gt; was already installed on my system through Homebrew.)&lt;/p&gt;
&lt;div class="code-block" data-lang="shell"&gt;&lt;pre&gt;&lt;code class="language-shell"&gt;$ brew install unixodbc mariadb-connector-odbc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;From here, I created a temporary file with the following contents (I named it &lt;code&gt;mariadb-odbc.ini&lt;/code&gt;).&lt;/p&gt;
&lt;div class="code-block" data-lang="ini"&gt;&lt;pre&gt;&lt;code class="language-ini"&gt;[MariaDB ODBC 3.1 Driver]
Description = MariaDB Connector/ODBC v.3.1
Driver = /usr/local/lib/mariadb/libmaodbc.dylib
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;libmaodbc&lt;/code&gt; driver is provided by &lt;code&gt;mariadb-connector-odbc&lt;/code&gt;, and the path to the &lt;code&gt;Driver&lt;/code&gt; is based on where Homebrew put it, so if you’re following along and attempting to do the same, double-check the location on your system.&lt;/p&gt;
&lt;p&gt;Then, I imported the driver configuration using &lt;code&gt;odbcinst&lt;/code&gt;, which comes with unixODBC. &lt;a href="http://www.unixodbc.org/odbcinst.html"&gt;Check the &lt;code&gt;odbcinst&lt;/code&gt; documentation&lt;/a&gt; for more information about the above INI file format.&lt;/p&gt;
&lt;div class="code-block" data-lang="shell"&gt;&lt;pre&gt;&lt;code class="language-shell"&gt;$ odbcinst -i -d -f mariadb-odbc.ini
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This adds the configuration to &lt;code&gt;/usr/local/etc/odbcinst.ini&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I then used Docker to create a MariaDB container that I could connect to using the ODBC driver.&lt;/p&gt;
&lt;div class="code-block" data-lang="shell"&gt;&lt;pre&gt;&lt;code class="language-shell"&gt;$ docker run -p 3306:3306 --name mariadb -e MYSQL_ROOT_PASSWORD=password -d mariadb:latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With the container up and running, I launched &lt;a href="https://psysh.org"&gt;PsySH&lt;/a&gt; and started entering expressions.&lt;/p&gt;
&lt;div class="code-block" data-lang="psysh"&gt;&lt;pre&gt;&lt;code class="language-psysh"&gt;&amp;gt; $dsn = &amp;quot;odbc:Driver={MariaDB ODBC 3.1 Driver};Server=127.0.0.1;Database=mysql;User=root;Password=password;Option=3;&amp;quot;

= &amp;quot;odbc:Driver={MariaDB ODBC 3.1 Driver};Server=127.0.0.1;Database=mysql;User=root;Password=password;Option=3;&amp;quot;

&amp;gt; $pdo = new PDO($dsn)

= PDO {#3907
     inTransaction: false,
     attributes: {
       CASE: NATURAL,
       ERRMODE: EXCEPTION,
       PERSISTENT: false,
       DRIVER_NAME: &amp;quot;odbc&amp;quot;,
       ORACLE_NULLS: NATURAL,
       CLIENT_VERSION: &amp;quot;ODBC-unixODBC&amp;quot;,
       STATEMENT_CLASS: [
         &amp;quot;PDOStatement&amp;quot;,
       ],
       DEFAULT_FETCH_MODE: BOTH,
     },
   }

&amp;gt; $pdo-&amp;gt;getAttribute(PDO::ATTR_SERVER_INFO)

   PDOException  SQLSTATE[IM001]: Driver does not support this function: driver does not support that attribute

&amp;gt; $pdo-&amp;gt;getAttribute(PDO::ATTR_SERVER_VERSION)

   PDOException  SQLSTATE[IM001]: Driver does not support this function: driver does not support that attribute
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So, there we go. &lt;code&gt;PDO::getAttribute()&lt;/code&gt; throws a &lt;code&gt;PDOException&lt;/code&gt; when it doesn’t support an attribute.&lt;/p&gt;
&lt;p&gt;Thanks to &lt;a href="https://github.com/NattyNarwhal"&gt;Calvin Buckley&lt;/a&gt;, these attributes will no longer throw exceptions and will instead &lt;a href="https://github.com/php/php-src/pull/6935"&gt;return actual values in PHP 8.1&lt;/a&gt;.&lt;/p&gt;
&lt;div class="code-block" data-lang="psysh"&gt;&lt;pre&gt;&lt;code class="language-psysh"&gt;&amp;gt; $pdo-&amp;gt;getAttribute(PDO::ATTR_SERVER_INFO)

= &amp;quot;MariaDB&amp;quot;

&amp;gt; $pdo-&amp;gt;getAttribute(PDO::ATTR_SERVER_VERSION)

= &amp;quot;10.05.000009&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
</content>
    <category term="php"/>
    <category term="odbc"/>
    <category term="mariadb"/>
    <rights type="html">Copyright © 2021 Ben Ramsey. Licensed for use under &lt;a href="https://creativecommons.org/licenses/by-sa/4.0/"&gt;CC BY-SA&lt;/a&gt;.</rights>
  </entry>
  <entry>
    <title type="text">Using CLion with php-src</title>
    <link rel="alternate" type="text/html" href="https://ben.ramsey.dev/blog/2021/05/php-src-with-clion"/>
    <published>2021-05-10T17:08:02+00:00</published>
    <updated>2021-05-10T17:08:02+00:00</updated>
    <id>urn:uuid:0179573f-fd50-7004-99ba-2aeb12171f38</id>
    <author>
      <name>Ben Ramsey</name>
      <email>ben@ramsey.dev</email>
    </author>
    <content type="html">&lt;aside class="admonition note" role="note"&gt;
&lt;h6 class="admonition-label"&gt;Note&lt;/h6&gt;
&lt;p&gt;
This post was originally published on &lt;a href="https://dev.to/ramsey/using-clion-with-php-src-4me0"&gt;DEV&lt;/a&gt;.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;I’ve cloned and built &lt;a href="https://github.com/php/php-src"&gt;php-src&lt;/a&gt; numerous times over the years, on a variety of platforms, but I’ve never worked with it in an IDE. A long-time &lt;a href="https://www.vim.org"&gt;Vim&lt;/a&gt; user, I’ve only begun using &lt;a href="https://www.jetbrains.com/phpstorm/"&gt;PhpStorm&lt;/a&gt; over the last year and a half, after seeing how &lt;a href="https://www.jetbrains.com/idea/"&gt;IntelliJ&lt;/a&gt; helped me easily navigate an open source Java project. So, in setting up php-src for &lt;a href="/blog/2021/05/php-release-manager"&gt;release management&lt;/a&gt; tasks, I wanted to give &lt;a href="https://www.jetbrains.com/clion/"&gt;CLion&lt;/a&gt; a try.&lt;/p&gt;
&lt;h2&gt;Getting php-src ready for CLion&lt;/h2&gt;
&lt;p&gt;When opening existing source code or cloning a repo with CLion, it assumes the project already supports &lt;a href="https://cmake.org"&gt;CMake&lt;/a&gt; tooling for builds. For someone new to C and using a project that doesn’t use CMake, this can be confusing and frustrating. Since php-src isn’t a CMake project, CLion will display warnings at the top of every open file, saying that a “CMake project is not loaded,” giving you the option to select or generate a &lt;code&gt;CMakeLists.txt&lt;/code&gt; file. You can try to do this for php-src, but there’s a better way.&lt;/p&gt;
&lt;p&gt;CLion also supports &lt;a href="https://www.jetbrains.com/help/clion/compilation-database.html"&gt;JSON compilation databases&lt;/a&gt;. To generate one and have CLion recognize php-src as a &lt;a href="https://www.jetbrains.com/help/clion/compilation-database.html"&gt;compilation database project&lt;/a&gt;, you’ll need to do the following &lt;em&gt;before&lt;/em&gt; opening php-src in CLion. If you’ve already opened it in CLion, that’s okay. Delete the &lt;code&gt;.idea/&lt;/code&gt; folder that CLion creates, and then do the following. (I could not figure out a way to make CLion recognize the compilation database if I had already opened the project in CLion. It seems the compilation database must exist the first time you open the project in order for CLion to recognize it.)&lt;/p&gt;
&lt;p&gt;You’ll need the &lt;code&gt;compiledb&lt;/code&gt; Python tool to generate the compilation database. It wraps the &lt;code&gt;make&lt;/code&gt; command, so when you run it with &lt;code&gt;make&lt;/code&gt;, it captures all the sources and creates a &lt;code&gt;compile_commands.json&lt;/code&gt; file. Then, when you open the project in CLion for the first time, it will recognize your project as a compilation database project.&lt;/p&gt;
&lt;div class="code-block" data-lang="shell"&gt;&lt;pre&gt;&lt;code class="language-shell"&gt;$ pip install compiledb

$ git clone https://github.com/php/php-src.git ~/repos/php/php-src
$ cd ~/repos/php/php-src
$ ./buildconf
$ ./configure \
    --prefix=$HOME/builds/php/8.1.0-dev \
    --disable-all \
    --disable-cgi \
    --enable-debug \
    --enable-zts

$ compiledb make
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see here, I use &lt;code&gt;compiledb&lt;/code&gt; to call &lt;code&gt;make&lt;/code&gt;. In this way, &lt;code&gt;compiledb&lt;/code&gt; can learn about all the sources for your build.&lt;/p&gt;
&lt;p&gt;You may also pass &lt;code&gt;-jN&lt;/code&gt; to &lt;code&gt;make&lt;/code&gt;, where &lt;code&gt;N&lt;/code&gt; is the number of CPU cores your system has available. This will greatly speed up compilation.&lt;/p&gt;
&lt;p&gt;You can run &lt;code&gt;nproc&lt;/code&gt; to find out how many cores you have.  On my system, I have 12 cores, so I run the command like this:&lt;/p&gt;
&lt;div class="code-block" data-lang="shell"&gt;&lt;pre&gt;&lt;code class="language-shell"&gt;$ compiledb make -j12
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In my example, I pass &lt;code&gt;--prefix&lt;/code&gt; to &lt;code&gt;configure&lt;/code&gt;, but this isn’t necessary since I’m not going to run &lt;code&gt;make install&lt;/code&gt;. Once &lt;code&gt;make&lt;/code&gt; has finished building PHP, you can find the newly-built PHP CLI at &lt;code&gt;sapi/cli/php&lt;/code&gt;.&lt;/p&gt;
&lt;div class="code-block" data-lang="shell"&gt;&lt;pre&gt;&lt;code class="language-shell"&gt;$ ./sapi/cli/php -v
PHP 8.1.0-dev (cli) (built: May  6 2021 18:27:37) (ZTS DEBUG)
Copyright (c) The PHP Group
Zend Engine v4.1.0-dev, Copyright (c) Zend Technologies

$ ./sapi/cli/php -m
[PHP Modules]
Core
date
hash
json
pcre
Reflection
SPL
standard

[Zend Modules]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Setting up CLion to build and run PHP&lt;/h2&gt;
&lt;p&gt;Now that php-src has a compilation database (which needs to be updated each time you change your build with &lt;code&gt;configure&lt;/code&gt; or if you add new sources that get included in &lt;code&gt;make&lt;/code&gt;), you can open it in CLion.&lt;/p&gt;
&lt;p&gt;Launch CLion to get to the welcome screen and choose to open a project from existing sources.&lt;/p&gt;
&lt;figure&gt;&lt;p&gt;&lt;a href="https://files.benramsey.com/ws/blog/2021-05-10-php-src-with-clion/01-clion-welcome-screen.png"&gt;&lt;img title="CLion welcome screen" src="https://files.benramsey.com/ws/blog/2021-05-10-php-src-with-clion/01-clion-welcome-screen.png" alt="CLion welcome screen" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figcaption&gt;&lt;strong&gt;Figure 1.&lt;/strong&gt; CLion welcome screen.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Browse to your php-src folder and, rather than selecting the folder to open, select the &lt;code&gt;compile_commands.json&lt;/code&gt; file that 	&lt;code&gt;compiledb&lt;/code&gt; generated.&lt;/p&gt;
&lt;figure&gt;&lt;p&gt;&lt;a href="https://files.benramsey.com/ws/blog/2021-05-10-php-src-with-clion/02-file-selection-dialog.png"&gt;&lt;img title="File selection dialog highlighting compile_commands.json" src="https://files.benramsey.com/ws/blog/2021-05-10-php-src-with-clion/02-file-selection-dialog.png" alt="File selection dialog highlighting compile_commands.json" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figcaption&gt;&lt;strong&gt;Figure 2.&lt;/strong&gt; File selection dialog highlighting &lt;code&gt;compile_commands.json&lt;/code&gt;.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;When CLion prompts you, choose to open it as a project.&lt;/p&gt;
&lt;figure&gt;&lt;p&gt;&lt;a href="https://files.benramsey.com/ws/blog/2021-05-10-php-src-with-clion/03-open-project-dialog.png"&gt;&lt;img title="&amp;quot;Open Project&amp;quot; dialog with the &amp;quot;Open as Project&amp;quot; button highlighted" src="https://files.benramsey.com/ws/blog/2021-05-10-php-src-with-clion/03-open-project-dialog.png" alt="“Open Project“ dialog with the “Open as Project” button highlighted" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figcaption&gt;&lt;strong&gt;Figure 3.&lt;/strong&gt; “Open Project” dialog with the “Open as Project” button highlighted.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;CLion will now open the project and inform you that it successfully imported the compilation database project.&lt;/p&gt;
&lt;figure&gt;&lt;p&gt;&lt;a href="https://files.benramsey.com/ws/blog/2021-05-10-php-src-with-clion/04-compilation-database-imported.png"&gt;&lt;img title="Compilation database project successfully imported" src="https://files.benramsey.com/ws/blog/2021-05-10-php-src-with-clion/04-compilation-database-imported.png" alt="Compilation database project successfully imported" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figcaption&gt;&lt;strong&gt;Figure 4.&lt;/strong&gt; Compilation database project successfully imported.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;With CLion open, you’ll now &lt;a href="https://www.jetbrains.com/help/clion/custom-build-targets.html"&gt;create custom build targets&lt;/a&gt; for &lt;code&gt;make&lt;/code&gt; and &lt;code&gt;make clean&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Open CLion Preferences and go to &lt;em&gt;Build, Execution, Deployment&lt;/em&gt; -&amp;gt; &lt;em&gt;Custom Build Targets&lt;/em&gt;. Create a new build target, named something like “Build PHP.” Then, next to the empty Build and Clean fields, click the &lt;em&gt;more&lt;/em&gt; button (with three dots). This will open an External Tools window. Use the +-button here to create two external tools.&lt;/p&gt;
&lt;p&gt;I named the first one “Build with Make.” The program is &lt;code&gt;make&lt;/code&gt; and I added &lt;code&gt;-j12&lt;/code&gt; to the arguments for a faster build (see earlier). You might also consider using &lt;code&gt;compiledb&lt;/code&gt; as the program, with &lt;code&gt;make -j12&lt;/code&gt; as the arguments.&lt;/p&gt;
&lt;figure&gt;&lt;p&gt;&lt;a href="https://files.benramsey.com/ws/blog/2021-05-10-php-src-with-clion/05-build-with-make.png"&gt;&lt;img title="&amp;quot;Build with Make&amp;quot; external tool" src="https://files.benramsey.com/ws/blog/2021-05-10-php-src-with-clion/05-build-with-make.png" alt="Build with Make“ external tool" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figcaption&gt;&lt;strong&gt;Figure 5.&lt;/strong&gt; Set up a “Build with Make” external tool.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;I named the second tool “Clean with Make” and used &lt;code&gt;make&lt;/code&gt; as the program and &lt;code&gt;clean&lt;/code&gt; as the argument.&lt;/p&gt;
&lt;figure&gt;&lt;p&gt;&lt;a href="https://files.benramsey.com/ws/blog/2021-05-10-php-src-with-clion/06-clean-with-make.png"&gt;&lt;img title="&amp;quot;Clean with Make&amp;quot; external tool" src="https://files.benramsey.com/ws/blog/2021-05-10-php-src-with-clion/06-clean-with-make.png" alt="“Clean with Make“ external tool" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figcaption&gt;&lt;strong&gt;Figure 6.&lt;/strong&gt; Set up a “Clean with Make” external tool.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Now, you can click OK to close these windows and the External Tools window, and select the proper tools to use with your Build PHP target.&lt;/p&gt;
&lt;figure&gt;&lt;p&gt;&lt;a href="https://files.benramsey.com/ws/blog/2021-05-10-php-src-with-clion/07-build-php-target.png"&gt;&lt;img title="&amp;quot;Build PHP&amp;quot; build target with external tools selected" src="https://files.benramsey.com/ws/blog/2021-05-10-php-src-with-clion/07-build-php-target.png" alt="“Build PHP“ build target with external tools selected" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figcaption&gt;&lt;strong&gt;Figure 7.&lt;/strong&gt; Set up a “Build PHP” build target external tool.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Finally, you’ll want to &lt;a href="https://www.jetbrains.com/help/clion/custom-build-targets.html#custom-rundebug"&gt;create a custom run/debug configuration&lt;/a&gt;.  To do this, go to &lt;em&gt;Run&lt;/em&gt; -&amp;gt; &lt;em&gt;Edit Configurations…&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Use the +-button to create a new configuration and choose &lt;strong&gt;Custom Build Application&lt;/strong&gt; from the menu that appears. I named my configuration “Build PHP” and I chose my “Build PHP” target (created earlier) from the Target dropdown list. For the executable, I entered the path to the PHP CLI built by this project (remember, it’s at &lt;code&gt;sapi/cli/php&lt;/code&gt;). Last, I checked “Redirect input from” and entered the JetBrains variable &lt;code&gt;$FilePrompt$&lt;/code&gt;. In this way, whenever you chose to run PHP from within CLion, it will prompt you with a file dialog to execute through the PHP interpreter. This lets you select a PHP script to run and test/debug whatever feature you’re working on.&lt;/p&gt;
&lt;figure&gt;&lt;p&gt;&lt;a href="https://files.benramsey.com/ws/blog/2021-05-10-php-src-with-clion/08-build-php-run-config.png"&gt;&lt;img title="&amp;quot;Build PHP&amp;quot; run/debug configuration" src="https://files.benramsey.com/ws/blog/2021-05-10-php-src-with-clion/08-build-php-run-config.png" alt="Build PHP“ run/debug configuration" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figcaption&gt;&lt;strong&gt;Figure 8.&lt;/strong&gt; Set up a “Build PHP” run/debug configuration.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Now, click the hammer icon (🔨) or select &lt;em&gt;Build&lt;/em&gt; -&amp;gt; &lt;em&gt;Build Project&lt;/em&gt; to build PHP, or select &lt;em&gt;Build&lt;/em&gt; -&amp;gt; &lt;em&gt;Clean&lt;/em&gt; to run the &lt;code&gt;make clean&lt;/code&gt; command.&lt;/p&gt;
&lt;figure&gt;&lt;p&gt;&lt;a href="https://files.benramsey.com/ws/blog/2021-05-10-php-src-with-clion/09-build-with-make-output.png"&gt;&lt;img title="Output after running &amp;quot;Build with Make&amp;quot;" src="https://files.benramsey.com/ws/blog/2021-05-10-php-src-with-clion/09-build-with-make-output.png" alt="Output after running “Build with Make”" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figcaption&gt;&lt;strong&gt;Figure 9.&lt;/strong&gt; Output after running “Build with Make.”&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;If you click the play icon (▶️) or choose &lt;em&gt;Run&lt;/em&gt; -&amp;gt; &lt;em&gt;Run ‘Build PHP’&lt;/em&gt;, it will prompt you to select a file and run that file as a PHP script. In the following, I’ve selected one of the &lt;code&gt;.phpt&lt;/code&gt; tests to execute this way.&lt;/p&gt;
&lt;figure&gt;&lt;p&gt;&lt;a href="https://files.benramsey.com/ws/blog/2021-05-10-php-src-with-clion/10-file-selection-phpt.png"&gt;&lt;img title="Using the file selection dialog to select a PHPT file to run" src="https://files.benramsey.com/ws/blog/2021-05-10-php-src-with-clion/10-file-selection-phpt.png" alt="Using the file selection dialog to select a PHPT file to run" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figcaption&gt;&lt;strong&gt;Figure 10.&lt;/strong&gt; Using the file selection dialog to select a PHPT file to run.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;p&gt;&lt;a href="https://files.benramsey.com/ws/blog/2021-05-10-php-src-with-clion/11-phpt-output.png"&gt;&lt;img title="Output after running the PHPT file" src="https://files.benramsey.com/ws/blog/2021-05-10-php-src-with-clion/11-phpt-output.png" alt="Output after running the PHPT file" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figcaption&gt;&lt;strong&gt;Figure 11.&lt;/strong&gt; Output after running the PHPT file.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2&gt;Step debugging through php-src&lt;/h2&gt;
&lt;p&gt;One of the primary reasons I wanted to use an IDE to work with php-src is for the debugging tools. With everything set up as described earlier, I’m able to run a PHP script and break on breakpoints in the C source code.&lt;/p&gt;
&lt;p&gt;As an example, I created a PHP script named &lt;code&gt;date-debug.php&lt;/code&gt; and added the following code to it.&lt;/p&gt;
&lt;div class="code-block" data-lang="php"&gt;&lt;pre&gt;&lt;code class="language-php"&gt;&amp;lt;?php
echo date('Y-m-d H:i:s', time());
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then, I opened &lt;code&gt;ext/date/php_date.c&lt;/code&gt; and placed a breakpoint in the &lt;code&gt;php_date()&lt;/code&gt; function. You can see the breakpoint in the following screenshot. I placed it right after the &lt;code&gt;ZEND_PARSE_PARAMETERS&lt;/code&gt; block.&lt;/p&gt;
&lt;p&gt;When you click the debug icon (🪲) or choose &lt;em&gt;Run&lt;/em&gt; -&amp;gt; &lt;em&gt;Debug ‘Build PHP’&lt;/em&gt;, CLion will prompt you to select a file, just like it does when when you click the play icon, as described earlier. When I choose the &lt;code&gt;date-debug.php&lt;/code&gt; file, it begins executing it and then stops at the breakpoint in the C code, which happens to be the code called when using the PHP &lt;code&gt;date()&lt;/code&gt; function. As you can see, I’m now able to examine the memory and variables in this function, including the &lt;a href="https://www.phpinternalsbook.com/php7/zvals.html"&gt;zvals&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;&lt;p&gt;&lt;a href="https://files.benramsey.com/ws/blog/2021-05-10-php-src-with-clion/12-breakpoint-inspection.png"&gt;&lt;img title="Inspecting variables at a breakpoint in the C source code for PHP" src="https://files.benramsey.com/ws/blog/2021-05-10-php-src-with-clion/12-breakpoint-inspection.png" alt="Inspecting variables at a breakpoint in the C source code for PHP" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figcaption&gt;&lt;strong&gt;Figure 12.&lt;/strong&gt; Inspecting variables at a breakpoint in the C source code for PHP.&lt;/figcaption&gt;&lt;/figure&gt;
</content>
    <category term="php"/>
    <category term="clion"/>
    <category term="jetbrains"/>
    <rights type="html">Copyright © 2021 Ben Ramsey. Licensed for use under &lt;a href="https://creativecommons.org/licenses/by-sa/4.0/"&gt;CC BY-SA&lt;/a&gt;.</rights>
  </entry>
  <entry>
    <title type="text">I'm a release manager for PHP 8.1!</title>
    <link rel="alternate" type="text/html" href="https://ben.ramsey.dev/blog/2021/05/php-release-manager"/>
    <published>2021-05-09T18:58:14+00:00</published>
    <updated>2021-05-09T18:58:14+00:00</updated>
    <id>urn:uuid:0179527e-8570-7017-bcf7-bd313bc0df9a</id>
    <author>
      <name>Ben Ramsey</name>
      <email>ben@ramsey.dev</email>
    </author>
    <content type="html">&lt;aside class="admonition note" role="note"&gt;
&lt;h6 class="admonition-label"&gt;Note&lt;/h6&gt;
&lt;p&gt;
This post was originally published on &lt;a href="https://dev.to/ramsey/i-m-a-release-manager-for-php-8-1-24i2"&gt;DEV&lt;/a&gt;.&lt;/p&gt;
&lt;/aside&gt;
&lt;aside class="admonition important" role="note"&gt;
&lt;h6 class="admonition-label"&gt;Important&lt;/h6&gt;
&lt;p&gt;
My permanent blog at &lt;a href="https://benramsey.com"&gt;benramsey.com&lt;/a&gt; is in a state where I am unable to update it. It’s a long story that involves versions of Ruby gems removed from the repository, trapping me in a tangled web of &lt;a href="https://jekyllrb.com"&gt;Jekyll&lt;/a&gt; dependency hell, and I haven’t had the stomach to unravel it. In the meantime, I’ll be posting here at &lt;a href="https://dev.to/ramsey"&gt;dev.to/ramsey&lt;/a&gt;.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Last year, I tossed my hat in the ring to volunteer as a release manager for PHP 8.0, but I lost the vote to &lt;a href="https://github.com/carusogabriel"&gt;Gabriel Caruso&lt;/a&gt;, who has shown himself to be a very capable RM for the 8.0 series (congrats, Gabriel, and great work!). This year, when &lt;a href="https://externals.io/message/113334"&gt;Sara announced the RM selection process&lt;/a&gt; for PHP 8.1, I almost decided against volunteering, but I finally decided to go for it, and I’m glad I did.&lt;/p&gt;
&lt;p&gt;Each set of release managers is usually comprised of a veteran RM and a rookie. This year, when &lt;a href="https://github.com/krakjoe"&gt;Joe Watkins&lt;/a&gt; volunteered as the veteran RM, he asked to take on two rookies. As a result, &lt;a href="https://github.com/patrickallaert"&gt;Patrick Allaert&lt;/a&gt; and I were &lt;a href="https://wiki.php.net/todo/php81"&gt;both selected as rookie RMs for the 8.1 series&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;PHP release managers manage the release process, create a roadmap for the release, facilitate discussions and decisions about what goes into a release, package the releases, etc. It’s a commitment of about three-and-a-half years, as they shepherd their minor version from alpha to beta to RC to GA to active support to security support and, finally, end-of-life. The &lt;a href="https://www.php.net/supported-versions.php"&gt;supported versions&lt;/a&gt; page at php.net provides a good overview of this cycle.&lt;/p&gt;
&lt;p&gt;You can read more about the PHP release process here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://wiki.php.net/rfc/releaseprocess"&gt;Request for Comments: Release Process&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/php/php-src/blob/master/docs/release-process.md"&gt;PHP release process&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Additionally, &lt;a href="https://twitter.com/shocm"&gt;Eric Van Johnson&lt;/a&gt; has published a three-part interview in &lt;em&gt;php[architect]&lt;/em&gt; magazine with PHP 8.0 release managers Sara Golemon and Gabriel Caruso. They go into a lot of the specifics.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.phparch.com/article/community-corner-php-8-release-managers-interview-with-sara-golemon-and-gabriel-caruso-part-1/"&gt;Community Corner: PHP 8 Release Managers: Interview with Sara Golemon and Gabriel Caruso, Part 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.phparch.com/article/community-corner-php-8-release-managers-interview-with-sara-golemon-and-gabriel-caruso-part-two/"&gt;Part 2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.phparch.com/article/community-corner-php-8-release-managers-interview-with-sara-golemon-and-gabriel-caruso-part-three/"&gt;Part 3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thank you so much to everyone for entrusting me to serve as one of the release managers for PHP 8.1! I look forward to working with Joe and Patrick over the next three-and-a-half years.&lt;/p&gt;
</content>
    <category term="php"/>
    <rights type="html">Copyright © 2021 Ben Ramsey. Licensed for use under &lt;a href="https://creativecommons.org/licenses/by-sa/4.0/"&gt;CC BY-SA&lt;/a&gt;.</rights>
  </entry>
  <entry>
    <title type="text">Thoughts on Software Architecture</title>
    <link rel="alternate" type="text/html" href="https://ben.ramsey.dev/blog/2019/04/software-architecture-thoughts"/>
    <published>2019-04-18T13:51:43+00:00</published>
    <updated>2019-04-18T13:51:43+00:00</updated>
    <id>urn:uuid:016a30b7-a598-7322-8547-bd0f93d9183a</id>
    <author>
      <name>Ben Ramsey</name>
      <email>ben@ramsey.dev</email>
    </author>
    <content type="html">&lt;aside class="admonition note" role="note"&gt;
&lt;h6 class="admonition-label"&gt;Note&lt;/h6&gt;
&lt;p&gt;
I originally posted this as &lt;a href="https://twitter.com/ramsey/status/1118331261079228417"&gt;a thread on Twitter&lt;/a&gt; in response to &lt;a href="https://twitter.com/ThePracticalDev/status/1118318764930551813"&gt;a #DevDiscuss topic&lt;/a&gt;. Then, I posted it &lt;a href="https://dev.to/ramsey/thoughts-on-software-architecture-898"&gt;on DEV&lt;/a&gt;. Now, I’m bringing it to my blog, where it belongs.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Software architecture concerns itself with how the software is built, including high-level design and technical standards, as well as coding standards, tools, platforms, etc.&lt;sup class="footnote-ref"&gt;&lt;a href="#fn:1" id="fnref:1" role="doc-noteref"&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;A software architect is a software developer who has become an expert in these things through extensive experience practicing them and learning from others.&lt;/p&gt;
&lt;p&gt;A software architect (as a role) is a leader in the organization, helping the team turn a problem domain into software. They are able to grasp the concepts of the domain and communicate how to represent them in code. Additionally, they work with the team to set standards and develop practices that will ensure the quality of the software created and the long-term maintainability of the code. They balance purity with pragmatism, considering the business goals and priorities—and they articulate the risk to the business when sacrificing quality/purity for accelerated timelines.&lt;/p&gt;
&lt;p&gt;I believe a software architect should be a mentor, using their experience to teach others how to create the best software they can. This involves in-depth code reviews and pair programming, among other teaching techniques. Good software architects are humble and patient. They don’t berate or belittle their team for not yet grasping concepts that they see clearly. Instead, they use these moments as teaching opportunities.&lt;/p&gt;
&lt;p&gt;Many see coding as formulaic as algebra equations. Software developers are natural problem-solvers, often seeing a code solution based on a formula before fully understanding the problem. Software architecture is different. There is no formula for it. There are recurring patterns seen across problem domains, and Martin Fowler has cataloged many, but his book Patterns of Enterprise Application Architecture cannot be treated as a formula by filling in the blanks and generating the code. It doesn’t work that way.&lt;/p&gt;
&lt;p&gt;Learning to design software from an architectural perspective is an exercise in &lt;a href="https://en.wikipedia.org/wiki/Grok"&gt;grokking&lt;/a&gt; the problem, taking a Zen-like approach to perceiving its true nature. To do this, you must exercise restraint so you don’t cloud your mind with thoughts of the solution before you fully understand the problem.&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;&lt;ol&gt;&lt;li class="footnote" id="fn:1" role="doc-endnote"&gt;&lt;p&gt;“Software architect.” &lt;em&gt;Wikipedia&lt;/em&gt;, &lt;a href="https://en.wikipedia.org/wiki/Software_architect"&gt;https://en.wikipedia.org/wiki/Software_architect&lt;/a&gt;.&amp;nbsp;&lt;a class="footnote-backref" rev="footnote" href="#fnref:1" role="doc-backlink"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
</content>
    <category term="software"/>
    <category term="architecture"/>
    <category term="architect"/>
    <category term="leadership"/>
    <rights type="html">Copyright © 2019 Ben Ramsey. Licensed for use under &lt;a href="https://creativecommons.org/licenses/by-sa/4.0/"&gt;CC BY-SA&lt;/a&gt;.</rights>
  </entry>
  <entry>
    <title type="text">Announcing PHP TestFest 2017</title>
    <link rel="alternate" type="text/html" href="https://ben.ramsey.dev/blog/2017/07/phptestfest"/>
    <published>2017-07-13T18:00:00+00:00</published>
    <updated>2017-07-13T18:00:00+00:00</updated>
    <id>http://benramsey.com/blog/2017/07/phptestfest</id>
    <author>
      <name>Ben Ramsey</name>
      <email>ben@ramsey.dev</email>
    </author>
    <content type="html">&lt;p&gt;For those who’ve been around the PHP community for a while, you’ll recall the successful PHP TestFest events that began after a &lt;a href="https://news-web.php.net/php.qa/64083"&gt;discussion at PHP Quebec in 2008&lt;/a&gt;. 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 &lt;em&gt;global&lt;/em&gt; sense from 2008 to 2010. After that, various groups (particularly the Brazilian groups) have continued the tradition.&lt;/p&gt;
&lt;p&gt;A few months ago, at php[tek] in Atlanta, I mentioned to &lt;a href="http://www.dragonbe.com/"&gt;Michelangelo&lt;/a&gt; that I’d love to bring back PHP TestFest. &lt;a href="https://www.sammyk.me/"&gt;Sammy&lt;/a&gt; had given &lt;a href="https://speakerdeck.com/sammyk/writing-tests-for-php-source-php-tek-2017"&gt;an excellent talk on writing PHPT tests&lt;/a&gt;, and &lt;a href="https://twitter.com/ellotheth/status/868583446498734084"&gt;Gemma tweeted&lt;/a&gt; a link to the &lt;a href="https://wiki.php.net/qa/testfest"&gt;old PHP TestFest wiki page&lt;/a&gt;. From there, things snowballed.&lt;/p&gt;
&lt;h2&gt;We’re bringing back PHP TestFest!&lt;/h2&gt;
&lt;p&gt;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 &lt;a href="mailto:sponsors@phptestfest.org"&gt;sponsors@phptestfest.org&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img class="right" width="40%" src="https://files.benramsey.com/ws/blog/2017-07-13-phptestfest/wooble-wave.svg" alt="Wooble" /&gt;&lt;/p&gt;
&lt;p&gt;This time around, I’ve set up a dedicated website at &lt;a href="https://phptestfest.org/"&gt;PHPTestFest.org&lt;/a&gt; and &lt;a href="https://groups.google.com/a/phpcommunity.org/group/testfest/"&gt;Google Group&lt;/a&gt; for discussion. We also have the &lt;a href="https://kiwiirc.com/client/irc.freenode.net#phptestfest"&gt;#phptestfest channel&lt;/a&gt; on Freenode IRC. All are encouraged to contribute to the &lt;a href="https://github.com/phpcommunity/phptestfest.org"&gt;website and tools repository&lt;/a&gt;. 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.&lt;/p&gt;
&lt;p&gt;I’ll be updating the “&lt;a href="https://phptestfest.org/start/"&gt;Getting Started&lt;/a&gt;” page on the PHP TestFest website soon with this information and more, so keep posted.&lt;/p&gt;
&lt;p&gt;Let’s get to work on improving code coverage of the PHP language!&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;em&gt;Special thanks to Sammy for letting us use “Wooble” as a testing mascot.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This announcement was cross-posted to the &lt;a href="https://news-web.php.net/php.qa/67968"&gt;php-qa&lt;/a&gt;, &lt;a href="https://news-web.php.net/ug.admins/1222"&gt;ug-admins&lt;/a&gt;, and &lt;a href="https://groups.google.com/a/phpcommunity.org/d/msg/testfest/FqGWMoKSiuc/EjE06bIBBwAJ"&gt;phptestfest&lt;/a&gt; mailing lists.&lt;/em&gt;&lt;/p&gt;
</content>
    <category term="phptestfest"/>
    <category term="phpt"/>
    <category term="testing"/>
    <rights type="html">Copyright © 2017 Ben Ramsey. Licensed for use under &lt;a href="https://creativecommons.org/licenses/by-sa/4.0/"&gt;CC BY-SA&lt;/a&gt;.</rights>
  </entry>
  <entry>
    <title type="text">Building PHP Projects on AWS CodeBuild</title>
    <link rel="alternate" type="text/html" href="https://ben.ramsey.dev/blog/2016/12/aws-codebuild-php"/>
    <published>2016-12-02T23:00:00+00:00</published>
    <updated>2016-12-02T23:00:00+00:00</updated>
    <id>http://benramsey.com/blog/2016/12/aws-codebuild-php</id>
    <author>
      <name>Ben Ramsey</name>
      <email>ben@ramsey.dev</email>
    </author>
    <summary type="html">&lt;p&gt;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.&lt;/p&gt;
</summary>
    <content type="html">&lt;p&gt;I’ve had a great time at &lt;a href="https://reinvent.awsevents.com/"&gt;AWS re:Invent&lt;/a&gt; this week, attending sessions and hanging out with some of the &lt;a href="https://www.shootproof.com/"&gt;ShootProof&lt;/a&gt; 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.&lt;/p&gt;
&lt;p&gt;Of course, the main highlight 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 &lt;a href="https://aws.amazon.com/codebuild/"&gt;AWS CodeBuild&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;CodeBuild is designed to be used as part of the &lt;a href="https://aws.amazon.com/codepipeline/"&gt;AWS CodePipeline&lt;/a&gt;, but it may also be used by itself. Additionally, with AWS’s increased focus on their container service (&lt;a href="https://aws.amazon.com/ecs/"&gt;ECS&lt;/a&gt;), it’s designed to integrate with ECS to use images you’ve stored in AWS, but it may also use images available on &lt;a href="https://hub.docker.com/"&gt;Docker Hub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;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 &lt;a href="https://github.com/ramsey/uuid"&gt;ramsey/uuid library&lt;/a&gt; for a simple test. Feel free to follow along with me.&lt;/p&gt;
&lt;h2&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;From your Amazon console, search for “CodeBuild” from the AWS Services search box, and choose it from the drop down menu that appears.&lt;/p&gt;
&lt;figure&gt;&lt;p&gt;&lt;img src="https://files.benramsey.com/ws/blog/2016-12-02-aws-codebuild-php/console-codebuild-search.png" alt="Search for CodeBuild from the AWS console" /&gt;&lt;/p&gt;
&lt;figcaption&gt;&lt;strong&gt;Figure 1.&lt;/strong&gt; Search for “CodeBuild” from the AWS console&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;figure&gt;&lt;p&gt;&lt;img src="https://files.benramsey.com/ws/blog/2016-12-02-aws-codebuild-php/codebuild-getting-started-2.png" alt="Search for CodeBuild from the AWS console" /&gt;&lt;/p&gt;
&lt;figcaption&gt;&lt;strong&gt;Figure 2.&lt;/strong&gt; Getting started with CodeBuild&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2&gt;Configuring Your Project&lt;/h2&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;First, provide a project name. Here, I’ve named the project “ramsey-uuid.”&lt;/p&gt;
&lt;p&gt;For &lt;em&gt;Source provider&lt;/em&gt;, 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 &lt;em&gt;Repository&lt;/em&gt; drop-down will be populated with a list of your GitHub repositories. Here, I’ve selected the uuid repository.&lt;/p&gt;
&lt;p&gt;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 &lt;em&gt;Environment image&lt;/em&gt; and choose “Other” for &lt;em&gt;Custom image type&lt;/em&gt;. For the &lt;em&gt;Custom image ID&lt;/em&gt;, I’m using &lt;code&gt;benramsey/composer-uuid:latest&lt;/code&gt; to specify the repository, image name, and image tag. You may place a &lt;a href="http://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html"&gt;&lt;em&gt;buildspec.yml&lt;/em&gt; file&lt;/a&gt; in the root of your repository to specify build commands (similar to a &lt;a href="https://docs.travis-ci.com/user/customizing-the-build"&gt;&lt;em&gt;.travis.yml&lt;/em&gt; file&lt;/a&gt;). Since ramsey/uuid doesn’t have a &lt;em&gt;buildspec.yml&lt;/em&gt; file, I’m specifying the &lt;em&gt;Build commands&lt;/em&gt; directly.&lt;/p&gt;
&lt;aside class="admonition warning" role="note"&gt;
&lt;h6 class="admonition-label"&gt;Warning&lt;/h6&gt;
&lt;p&gt;
While there is an &lt;a href="https://hub.docker.com/_/composer/"&gt;official Composer image on Docker Hub&lt;/a&gt;, it is currently based on the &lt;code&gt;php:7-alpine&lt;/code&gt; image (see the &lt;a href="https://github.com/composer/docker/blob/be6ecf58913f704399d11a352818b22951832a60/1.2/Dockerfile"&gt;Dockerfile&lt;/a&gt; for reference). The PHP image using &lt;a href="https://alpinelinux.org/"&gt;Alpine Linux&lt;/a&gt; will not run on AWS CodeBuild. Until this is resolved, I recommend using &lt;a href="http://robloach.net/"&gt;Rob Loach’s&lt;/a&gt; &lt;a href="https://hub.docker.com/r/composer/composer/"&gt;composer/composer image&lt;/a&gt;, which is what I have used as the basis for my &lt;a href="https://hub.docker.com/r/benramsey/composer-uuid/"&gt;benramsey/composer-uuid&lt;/a&gt; image.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;The full build command I’ve specified for ramsey/uuid is:&lt;/p&gt;
&lt;div class="code-block" data-lang="shell"&gt;&lt;pre&gt;&lt;code class="language-shell"&gt;$ composer install --no-interaction --prefer-dist \
    &amp;amp;&amp;amp; ./vendor/bin/parallel-lint src tests \
    &amp;amp;&amp;amp; ./vendor/bin/phpunit --verbose --no-coverage \
    &amp;amp;&amp;amp; ./vendor/bin/phpcs src tests --standard=psr2 -sp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally, I’m not generating any artifacts for this build, so I selected “No artifacts” for the &lt;em&gt;Artifacts type&lt;/em&gt;, and I chose to let it automatically create a service role in my account.&lt;/p&gt;
&lt;p&gt;Our project is now configured, so click &lt;em&gt;Continue&lt;/em&gt;, review your choices, click &lt;em&gt;Save and Build&lt;/em&gt;, then click &lt;em&gt;Start build&lt;/em&gt; to run a build.&lt;/p&gt;
&lt;figure&gt;&lt;p&gt;&lt;a href="https://files.benramsey.com/ws/blog/2016-12-02-aws-codebuild-php/codebuild-configure.png"&gt;&lt;img src="https://files.benramsey.com/ws/blog/2016-12-02-aws-codebuild-php/codebuild-configure.png" alt="Configure a CodeBuild project" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figcaption&gt;&lt;strong&gt;Figure 3.&lt;/strong&gt; Configure a project &lt;em&gt;(click to enlarge)&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2&gt;Building Your Project&lt;/h2&gt;
&lt;p&gt;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 &lt;em&gt;Succeeded&lt;/em&gt; in a comforting bold green.&lt;/p&gt;
&lt;figure&gt;&lt;p&gt;&lt;a href="https://files.benramsey.com/ws/blog/2016-12-02-aws-codebuild-php/codebuild-progress.png"&gt;&lt;img src="https://files.benramsey.com/ws/blog/2016-12-02-aws-codebuild-php/codebuild-progress.png" alt="View the progress of your project build" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figcaption&gt;&lt;strong&gt;Figure 4.&lt;/strong&gt; Project build progress &lt;em&gt;(click to enlarge)&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2&gt;What Next?&lt;/h2&gt;
&lt;p&gt;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:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Some of our tests talk to a dev database in a VPC. How do we grant VPC access to a container running in CodeBuild?&lt;/li&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;li&gt;What do we do about the other information we currently capture, like JUnit and Clover XML files?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;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.&lt;/p&gt;
</content>
    <category term="aws"/>
    <category term="reinvent"/>
    <category term="codebuild"/>
    <rights type="html">Copyright © 2016 Ben Ramsey. Licensed for use under &lt;a href="https://creativecommons.org/licenses/by-sa/4.0/"&gt;CC BY-SA&lt;/a&gt;.</rights>
  </entry>
  <entry>
    <title type="text">7 Tips for php[tek]</title>
    <link rel="alternate" type="text/html" href="https://ben.ramsey.dev/blog/2016/05/phptek-tips"/>
    <published>2016-05-22T00:00:00+00:00</published>
    <updated>2016-05-22T00:00:00+00:00</updated>
    <id>http://benramsey.com/blog/2016/05/phptek-tips</id>
    <author>
      <name>Ben Ramsey</name>
      <email>ben@ramsey.dev</email>
    </author>
    <content type="html">&lt;p&gt;This week, I’m attending &lt;a href="https://tek.phparch.com/"&gt;php[tek]&lt;/a&gt;. 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.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Hang out in the evenings, after the conference sessions.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;figure&gt;&lt;p&gt;&lt;img title="A crowd of people at a conference after party" src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek03.jpg" alt="A crowd of people at a conference after party" /&gt;&lt;/p&gt;
&lt;figcaption class="citation"&gt;&lt;em&gt;&lt;a href="https://www.flickr.com/photos/akrabat/8784385503/"&gt;Open bar…&lt;/a&gt;&lt;/em&gt;, by Rob Allen / &lt;a href="https://creativecommons.org/licenses/by-nc-sa/2.0/"&gt;CC BY-NC-SA&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;p&gt;&lt;img title="People at a conference after party playing Rock Band" src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek05.jpg" alt="People at a conference after party playing Rock Band" /&gt;&lt;/p&gt;
&lt;figcaption class="citation"&gt;&lt;em&gt;&lt;a href="https://www.flickr.com/photos/akrabat/4642947292/"&gt;Rock Band&lt;/a&gt;&lt;/em&gt;, by Rob Allen / &lt;a href="https://creativecommons.org/licenses/by-nd/2.0/"&gt;CC BY-ND&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;After the conference events, follow folks to the bar.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;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!&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I closed down Shoeless Joe’s with &lt;a href="https://twitter.com/cspruck"&gt;@cspruck&lt;/a&gt;, &lt;a href="https://twitter.com/ElizabethN"&gt;@ElizabethN&lt;/a&gt;,
&lt;a href="https://twitter.com/derickr"&gt;@derickr&lt;/a&gt;, &lt;a href="https://twitter.com/coderabbi"&gt;@coderabbi&lt;/a&gt;, &lt;a href="https://twitter.com/JimLindForPope"&gt;@JimLindForPope&lt;/a&gt;,
&lt;a href="https://twitter.com/dshafik"&gt;@dshafik&lt;/a&gt;, &lt;a href="https://twitter.com/ptahdunbar"&gt;@ptahdunbar&lt;/a&gt;, et al. #phptek&lt;/p&gt;
&lt;p&gt;— Ben Ramsey (&lt;a href="https://twitter.com/ramsey"&gt;@ramsey&lt;/a&gt;), May 23, 2014, &lt;cite&gt;&lt;a href="https://twitter.com/ramsey/status/469767931820511232"&gt;Twitter&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Take advantage of the “hallway track,” and don’t forget the regular sessions.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;figure&gt;&lt;p&gt;&lt;img title="A close-up of the board game Risk, played at a conference after party" src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek09.jpg" alt="A close-up of the board game Risk, played at a conference after party" /&gt;&lt;/p&gt;
&lt;figcaption class="citation"&gt;&lt;em&gt;&lt;a href="https://www.flickr.com/photos/eliw/19299729782/"&gt;Untitled&lt;/a&gt;&lt;/em&gt;, by Eli White / &lt;a href="https://creativecommons.org/licenses/by-sa/2.0/"&gt;CC BY-SA&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;p&gt;&lt;img title="Headshot of Ligaya Turmelle, standing on the 'red carpet' in front of a wall of sponsor logos" src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek14.jpg" alt="Headshot of Ligaya Turmelle, standing on the “red carpet” in front of a wall of sponsor logos" /&gt;&lt;/p&gt;
&lt;figcaption class="citation"&gt;&lt;em&gt;&lt;a href="https://www.flickr.com/photos/blueparabola/5759017486/"&gt;tek11 – Red Carpet&lt;/a&gt;&lt;/em&gt;, by Blue Parabola / &lt;a href="https://creativecommons.org/licenses/by-nc-sa/2.0/"&gt;CC BY-NC-SA&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;p&gt;&lt;img title="Lego creations at a conference after party" src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek15.jpg" alt="Lego creations at a conference after party" /&gt;&lt;/p&gt;
&lt;figcaption class="citation"&gt;&lt;em&gt;&lt;a href="https://www.flickr.com/photos/benandliz/26982337936/"&gt;php[tek] 2013&lt;/a&gt;&lt;/em&gt;, by Ben Ramsey / &lt;a href="https://creativecommons.org/licenses/by-sa/2.0/"&gt;CC BY-SA&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Attend the morning keynote sessions.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The morning keynote sessions set the tone for the conference, and &lt;a href="https://tek16.phparch.com/schedule/"&gt;this year’s keynotes&lt;/a&gt; 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.&lt;/p&gt;
&lt;figure&gt;&lt;p&gt;&lt;img title="Four people dressed up like the rock band Kiss, complete with makeup, wigs, and full costumes, at a conference after party" src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek10.jpg" alt="Four people dressed up like the rock band Kiss, complete with makeup, wigs, and full costumes, at a conference after party" /&gt;&lt;/p&gt;
&lt;figcaption class="citation"&gt;&lt;em&gt;&lt;a href="https://www.flickr.com/photos/rbowen/2523296126/"&gt;PHP Rock Stars&lt;/a&gt;&lt;/em&gt;, by Rich Bowen / &lt;a href="https://creativecommons.org/licenses/by/2.0/"&gt;CC BY&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure class="left"&gt;&lt;p&gt;&lt;img title="A paper sign that reads 'It is forbidden to parachute blue elephants in the lobby. —The management'" src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek12.jpg" alt="A paper sign that reads “It is forbidden to parachute blue elephants in the lobby. —The management”" /&gt;&lt;/p&gt;
&lt;figcaption class="citation"&gt;&lt;em&gt;&lt;a href="https://www.flickr.com/photos/sebastian_bergmann/2527709508/"&gt;It is forbidden…&lt;/a&gt;&lt;/em&gt;, by Sebastian Bergmann&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure class="right"&gt;&lt;p&gt;&lt;img title="A very tall mug of root beer beer" src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek13.jpg" alt="A very tall mug of root beer beer" /&gt;&lt;/p&gt;
&lt;figcaption class="citation"&gt;&lt;em&gt;&lt;a href="https://www.flickr.com/photos/benandliz/27015991995/"&gt;php[tek] 2014: Root beer beer&lt;/a&gt;&lt;/em&gt;, by Ben Ramsey / &lt;a href="https://creativecommons.org/licenses/by-sa/2.0/"&gt;CC BY-SA&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;p&gt;&lt;img title="A window filled halfway with plush, blue stuffed elephants" src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek11.jpg" alt="A window filled halfway with plush, blue stuffed elephants" /&gt;&lt;/p&gt;
&lt;figcaption class="citation"&gt;&lt;em&gt;&lt;a href="https://www.flickr.com/photos/preinheimer/2508587135/"&gt;The Elephpants are coming!&lt;/a&gt;&lt;/em&gt;, by Paul Reinheimer&lt;/figcaption&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Join the conference IRC backchannel: #phptek on Freenode.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The #phptek channel on Freenode IRC is the conference backchannel. If you’re unfamiliar with IRC or don’t have an IRC program, &lt;a href="http://webchat.freenode.net/?channels=#phptek"&gt;use Freenode’s free webchat&lt;/a&gt; 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.&lt;/p&gt;
&lt;figure&gt;&lt;p&gt;&lt;img title="A crowd of people eating deep dish pizza" src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek01.jpg" alt="A crowd of people eating deep dish pizza" /&gt;&lt;/p&gt;
&lt;figcaption class="citation"&gt;&lt;em&gt;&lt;a href="https://www.flickr.com/photos/89711680@N00/2511405443/"&gt;Untitled&lt;/a&gt;&lt;/em&gt;, by Timothy Boronczyk&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;p&gt;&lt;img title="Three people participating in a conga line at a conference after party" src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek04.jpg" alt="Three people participating in a conga line at a conference after party" /&gt;&lt;/p&gt;
&lt;figcaption class="citation"&gt;&lt;em&gt;&lt;a href="https://www.flickr.com/photos/akrabat/4639332391/"&gt;Party!&lt;/a&gt;&lt;/em&gt;, by Rob Allen / &lt;a href="https://creativecommons.org/licenses/by-nd/2.0/"&gt;CC BY-ND&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;p&gt;&lt;img title="Another crowd of people eating deep dish pizza, this time looking at the camera" src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek02.jpg" alt="Another crowd of people eating deep dish pizza, this time looking at the camera" /&gt;&lt;/p&gt;
&lt;figcaption class="citation"&gt;&lt;em&gt;&lt;a href="https://www.flickr.com/photos/89711680@N00/2511404709/"&gt;Untitled&lt;/a&gt;&lt;/em&gt;, by Timothy Boronczyk&lt;/figcaption&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Use the official hashtag: #phptek&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The conference’s official hashtag is #phptek. Not #tek. Not #tek16. It’s #phptek. Use it when posting on &lt;a href="https://twitter.com/search?f=tweets&amp;amp;q=%23phptek"&gt;Twitter&lt;/a&gt;. Use it for posts to &lt;a href="https://www.instagram.com/explore/tags/phptek/"&gt;Instagram&lt;/a&gt;. Search nearby check-ins on &lt;a href="https://www.swarmapp.com/"&gt;Swarm&lt;/a&gt;. Use it on your photo uploads to &lt;a href="https://www.flickr.com/"&gt;Flickr&lt;/a&gt;. 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].&lt;/p&gt;
&lt;figure&gt;&lt;p&gt;&lt;img title="Six women dressed up in evening gowns" src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek08.jpg" alt="Six women dressed up in evening gowns" /&gt;&lt;/p&gt;
&lt;figcaption class="citation"&gt;&lt;em&gt;&lt;a href="https://www.flickr.com/photos/derickrethans/3604018693/"&gt;phpwomen shoot&lt;/a&gt;&lt;/em&gt;, by Derick Rethans&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;p&gt;&lt;img title="Ten dudes all wearing 'I support PHP Women' t-shirts" src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek06.jpg" alt="Ten dudes all wearing “I support PHP Women” t-shirts" /&gt;&lt;/p&gt;
&lt;figcaption class="citation"&gt;&lt;em&gt;&lt;a href="https://www.flickr.com/photos/derickrethans/3604849316/"&gt;The phpwoman boothbabes&lt;/a&gt;&lt;/em&gt;, by Derick Rethans&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;p&gt;&lt;img title="One person raises a slice of deep dish pizza high in the air, the cheese trailing far below, while another twirls the end of the cheese trail with their fork" src="https://files.benramsey.com/ws/blog/2016-05-22-phptek-tips/phptek07.jpg" alt="One person raises a slice of deep dish pizza high in the air, the cheese trailing far below, while another twirls the end of the cheese trail with their fork" /&gt;&lt;/p&gt;
&lt;figcaption class="citation"&gt;&lt;em&gt;&lt;a href="https://www.flickr.com/photos/akrabat/4639320697/"&gt;Chicago style pizza!&lt;/a&gt;&lt;/em&gt;, by Rob Allen / &lt;a href="https://creativecommons.org/licenses/by-nd/2.0/"&gt;CC BY-ND&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Take lots of pictures and upload them to Flickr.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you don’t have a Flickr account, &lt;a href="https://www.flickr.com/"&gt;go get one&lt;/a&gt;. 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 &lt;a href="https://creativecommons.org/"&gt;Creative Commons&lt;/a&gt; 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]:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.flickr.com/search/?sort=date-taken-desc&amp;amp;view_all=1&amp;amp;tags=(phptek%20OR%20tek06)&amp;amp;min_taken_date=1145682000&amp;amp;max_taken_date=1146373199"&gt;php|tek 2006&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.flickr.com/search/?sort=date-taken-desc&amp;amp;view_all=1&amp;amp;tags=(phptek%20OR%20tek07)&amp;amp;min_taken_date=1178946000&amp;amp;max_taken_date=1179723599"&gt;php|tek 2007&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.flickr.com/search/?sort=date-taken-desc&amp;amp;view_all=1&amp;amp;tags=(phptek%20OR%20tek08)&amp;amp;min_taken_date=1211173200&amp;amp;max_taken_date=1211864399"&gt;php|tek 2008&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.flickr.com/search/?sort=date-taken-desc&amp;amp;min_taken_date=1242363600&amp;amp;max_taken_date=1243227599&amp;amp;view_all=1&amp;amp;tags=(phptek%20OR%20tek09)"&gt;php|tek 2009&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.flickr.com/search/?sort=date-taken-desc&amp;amp;min_taken_date=1273726800&amp;amp;max_taken_date=1274763599&amp;amp;view_all=1&amp;amp;tags=(phptek%20OR%20tek10%20OR%20tekx)"&gt;php|tek 2010&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.flickr.com/search/?sort=date-taken-desc&amp;amp;view_all=1&amp;amp;tags=(phptek%20OR%20tek11)&amp;amp;min_taken_date=1305954000&amp;amp;max_taken_date=1306904399"&gt;php|tek 2011&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.flickr.com/search/?sort=date-taken-desc&amp;amp;min_taken_date=1337576400&amp;amp;max_taken_date=1338181199&amp;amp;view_all=1&amp;amp;tags=(phptek%20OR%20tek12)"&gt;php|tek 2012&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.flickr.com/search/?sort=date-taken-desc&amp;amp;view_all=1&amp;amp;tags=(phptek%20OR%20tek13)&amp;amp;min_taken_date=1368334800&amp;amp;max_taken_date=1371877199"&gt;php[tek] 2013&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.flickr.com/search/?sort=date-taken-desc&amp;amp;view_all=1&amp;amp;tags=(phptek%20OR%20tek14)&amp;amp;min_taken_date=1400302800&amp;amp;max_taken_date=1400993999"&gt;php[tek] 2014&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.flickr.com/search/?sort=date-taken-desc&amp;amp;view_all=1&amp;amp;tags=(phptek%20OR%20tek15)&amp;amp;min_taken_date=1431838800&amp;amp;max_taken_date=1432443599"&gt;php[tek] 2015&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;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!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.flickr.com/search/?sort=date-taken-desc&amp;amp;min_taken_date=1463806800&amp;amp;max_taken_date=1464584399&amp;amp;view_all=1&amp;amp;tags=(phptek%20OR%20tek16)"&gt;php[tek] 2016&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;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 &lt;a href="https://twitter.com/ramsey/status/818465884"&gt;Terry Chay Fuck Counter&lt;/a&gt;; &lt;a href="https://twitter.com/ramsey/status/1840517481"&gt;hosted PHP internals meetings&lt;/a&gt;; started the PHP standards group that morphed into the PHP-FIG; held sessions on &lt;a href="https://twitter.com/ramsey/status/1874399223"&gt;community leadership&lt;/a&gt; and &lt;a href="https://twitter.com/CaseySoftware/status/14435677111"&gt;panels on running user groups&lt;/a&gt;; created numerous unseemly, alliterative names for our favorite local sports bar; drank lots of &lt;a href="https://twitter.com/ramsey/status/334540479406415872"&gt;root beer&lt;/a&gt;; held summits on mentoring, mental health, and open source; experienced &lt;a href="https://twitter.com/ramsey/status/335056094340739074"&gt;Ed Finkler’s first presentation&lt;/a&gt; on “Open Sourcing Mental Illness;” exposed the &lt;a href="https://twitter.com/ieatkillerbees/status/471469033829986305"&gt;PHP Bard&lt;/a&gt;; and much, much more.&lt;/p&gt;
&lt;p&gt;The last nine years in Chicago have been amazing for php[tek]. I can’t wait to see what St. Louis will bring.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;They’ve still not replaced the bat at Shoeless Joe’s. #phptek &lt;a href="https://twitter.com/joshholmes"&gt;@joshholmes&lt;/a&gt; https://pic.twitter.com/E4TNdXYGDs&lt;/p&gt;
&lt;p&gt;— Ben Ramsey (&lt;a href="https://twitter.com/ramsey"&gt;@ramsey&lt;/a&gt;), May 21, 2015, &lt;cite&gt;&lt;a href="https://twitter.com/ramsey/status/601266919212240896"&gt;Twitter&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;One last root beer beer. Cheers! &lt;a href="https://twitter.com/paleozombie"&gt;@paleozombie&lt;/a&gt; &lt;a href="https://twitter.com/ramsey"&gt;@ramsey&lt;/a&gt; &lt;a href="https://twitter.com/kevinbruce"&gt;@kevinbruce&lt;/a&gt; &lt;a href="https://twitter.com/SandyS1"&gt;@SandyS1&lt;/a&gt; &lt;a href="https://twitter.com/EliW"&gt;@EliW&lt;/a&gt; &lt;a href="https://twitter.com/CattyCreations"&gt;@CattyCreations&lt;/a&gt; &lt;a href="https://twitter.com/omerida"&gt;@omerida&lt;/a&gt; #phptek https://pic.twitter.com/2Vy7JD6gJt&lt;/p&gt;
&lt;p&gt;— Beth Tucker Long (&lt;a href="https://twitter.com/e3BethT"&gt;@e3BethT&lt;/a&gt;), May 23, 2015, &lt;cite&gt;&lt;a href="https://twitter.com/e3BethT/status/601928243768266752"&gt;Twitter&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;My biggest take away from #phptek is that, as a community, we are starting to think about each other as people. That’s pretty cool&lt;/p&gt;
&lt;p&gt;— Jeff Carouth (&lt;a href="https://twitter.com/jcarouth"&gt;@jcarouth&lt;/a&gt;), May 24, 2015, &lt;cite&gt;&lt;a href="https://twitter.com/jcarouth/status/602286254483451904"&gt;Twitter&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content>
    <category term="phptek"/>
    <rights type="html">Copyright © 2016 Ben Ramsey. Licensed for use under &lt;a href="https://creativecommons.org/licenses/by-sa/4.0/"&gt;CC BY-SA&lt;/a&gt;.</rights>
  </entry>
  <entry>
    <title type="text">Mastering OAuth 2.0 Published</title>
    <link rel="alternate" type="text/html" href="https://ben.ramsey.dev/blog/2016/05/mastering-oauth2-published"/>
    <published>2016-05-15T02:00:00+00:00</published>
    <updated>2016-05-15T02:00:00+00:00</updated>
    <id>http://benramsey.com/blog/2016/05/mastering-oauth2-published</id>
    <author>
      <name>Ben Ramsey</name>
      <email>ben@ramsey.dev</email>
    </author>
    <content type="html">&lt;p&gt;&lt;a href="https://www.phparch.com/magazine/2016-2/may/"&gt;&lt;img class="right" src="https://files.benramsey.com/ws/blog/2016-05-14-mastering-oauth2/cover-232x300.png" alt="php[architect] May 2016" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I’ve published my first article in &lt;a href="https://www.phparch.com/"&gt;&lt;em&gt;php[architect]&lt;/em&gt; magazine&lt;/a&gt; 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.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;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 &lt;a href="https://twitter.com/omerida"&gt;Oscar&lt;/a&gt; a few beers at &lt;a href="https://tek.phparch.com"&gt;php[tek]&lt;/a&gt; for putting him through that.&lt;/p&gt;
&lt;h2&gt;Mistakes Were Made&lt;/h2&gt;
&lt;p&gt;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 &lt;a href="http://developers.instagram.com/post/133424514006/instagram-platform-update"&gt;Instagram deprecated the &lt;code&gt;/users/self/feed&lt;/code&gt; endpoint&lt;/a&gt; (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.&lt;/p&gt;
&lt;aside class="admonition note" role="note"&gt;
&lt;h6 class="admonition-label"&gt;Note&lt;/h6&gt;
&lt;p&gt;
There is a full, working &lt;a href="https://github.com/ramsey/oauth2-phparch/releases/tag/phparch-may2016"&gt;package of code available for download&lt;/a&gt; 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 &lt;a href="https://github.com/ramsey/oauth2-phparch/blob/phparch-may2016/readme.md"&gt;readme.md file&lt;/a&gt; to find out how to run it.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;Fortunately, there’s an easy fix for this. In &lt;strong&gt;Listing 2&lt;/strong&gt; of my article’s example code (app/Http/Controllers/HomeController.php), you’ll find the following lines of code:&lt;/p&gt;
&lt;div class="code-block" data-lang="php"&gt;&lt;pre&gt;&lt;code class="language-php"&gt;$feedRequest = Instagram::getAuthenticatedRequest(
    'GET',
    'https://api.instagram.com/v1/users/self/feed',
    $instagramToken
);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This code uses the deprecated Instagram endpoint &lt;code&gt;https://api.instagram.com/v1/users/self/feed&lt;/code&gt;. There is no replacement for this endpoint, but we can substitute it with another one: &lt;code&gt;https://api.instagram.com/v1/users/self/media/recent&lt;/code&gt;. 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:&lt;/p&gt;
&lt;div class="code-block" data-lang="php"&gt;&lt;pre&gt;&lt;code class="language-php"&gt;$feedRequest = Instagram::getAuthenticatedRequest(
    'GET',
    'https://api.instagram.com/v1/users/self/media/recent',
    $instagramToken
);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Thanks For Reading&lt;/h3&gt;
&lt;p&gt;If you took the time to read the article, thank you so much. If you haven’t yet, &lt;a href="https://www.phparch.com/magazine/2016-2/may/"&gt;go grab a copy of the May issue and read it&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;On Twitter, I posted a thread of tweets where I mention a few things about OAuth and then list many of the &lt;em&gt;php[architect]&lt;/em&gt; articles that have covered it. Feel free to read through this conversation and check out the other OAuth articles to increase your own understanding.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;While OAuth is used practically everywhere these days, there’s still so much misunderstanding around how it works. #oauth (1/12)&lt;/p&gt;
&lt;p&gt;— Ben Ramsey (&lt;a href="https://twitter.com/ramsey"&gt;@ramsey&lt;/a&gt;) May 13, 2016, &lt;cite&gt;&lt;a href="https://twitter.com/ramsey/status/731215630062485505"&gt;Twitter&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Finally, my friend &lt;a href="https://twitter.com/shrtwhitebldguy"&gt;Matt Frost&lt;/a&gt; recently wrote &lt;a href="http://phpa.me/oauthbook"&gt;&lt;em&gt;Integrating Web Services with OAuth and PHP&lt;/em&gt;&lt;/a&gt;, also published by the good folks at &lt;em&gt;php[architect]&lt;/em&gt;. Check it out to learn more about OAuth versions 1 and 2.&lt;/p&gt;
</content>
    <category term="oauth"/>
    <rights type="html">Copyright © 2016 Ben Ramsey. Licensed for use under &lt;a href="https://creativecommons.org/licenses/by-sa/4.0/"&gt;CC BY-SA&lt;/a&gt;.</rights>
  </entry>
  <entry>
    <title type="text">Post-Open Source</title>
    <link rel="alternate" type="text/html" href="https://ben.ramsey.dev/blog/2016/04/post-open-source"/>
    <published>2016-04-26T00:00:00+00:00</published>
    <updated>2016-04-26T00:00:00+00:00</updated>
    <id>http://benramsey.com/blog/2016/04/post-open-source</id>
    <author>
      <name>Ben Ramsey</name>
      <email>ben@ramsey.dev</email>
    </author>
    <content type="html">&lt;p&gt;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, “&lt;a href="https://seld.be/notes/common-files-in-php-packages"&gt;Common files in PHP packages&lt;/a&gt;,” got me thinking about the lack of open source licenses in public repositories.&lt;/p&gt;
&lt;p&gt;In his post, Jordi explains how he analyzed all packages at &lt;a href="https://packagist.org/"&gt;Packagist&lt;/a&gt;, 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:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;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&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In a &lt;a href="https://web.archive.org/web/20130729012321/http://www.softwarefreedom.org/resources/2013/lcs-slides-aaronw/#/begin"&gt;2013 analysis&lt;/a&gt; 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&lt;sup class="footnote-ref"&gt;&lt;a href="#fn:analysis" id="fnref:analysis" role="doc-noteref"&gt;[1]&lt;/a&gt;&lt;/sup&gt;. 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.”&lt;/p&gt;
&lt;blockquote class="pullquote"&gt;
&lt;p&gt;Why are so few repositories adding open source licenses?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="https://web.archive.org/web/20150125172854/https://lu.is/blog/2013/01/27/taking-post-open-source-seriously-as-a-statement-about-copyright-law/"&gt;Luis Villa posits&lt;/a&gt; it might be because developers are rejecting permission culture.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;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”?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;younger devs today are about POSS – Post open source software. fuck the license and governance, just commit to github.&lt;/p&gt;
&lt;p&gt;— James Governor (&lt;a href="https://twitter.com/monkchips"&gt;@monkchips&lt;/a&gt;), September 17, 2012, &lt;cite&gt;&lt;a href="https://twitter.com/monkchips/status/247584170967175169"&gt;Twitter&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;In Lawrence Lessig’s 2004 book &lt;em&gt;Free Culture&lt;/em&gt;, Lessig warned:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;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 &lt;em&gt;permission&lt;/em&gt; to use it.&lt;/p&gt;
&lt;p&gt;What do you think? Do open source licenses propagate permission culture? Are we in a post-open source era?&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;&lt;ol&gt;&lt;li class="footnote" id="fn:analysis" role="doc-endnote"&gt;&lt;p&gt;The analysis used &lt;a href="http://www.fossology.org/"&gt;FOSSology&lt;/a&gt; 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.).&amp;nbsp;&lt;a class="footnote-backref" rev="footnote" href="#fnref:analysis" role="doc-backlink"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
</content>
    <category term="opensource"/>
    <rights type="html">Copyright © 2016 Ben Ramsey. Licensed for use under &lt;a href="https://creativecommons.org/licenses/by-sa/4.0/"&gt;CC BY-SA&lt;/a&gt;.</rights>
  </entry>
  <entry>
    <title type="text">Introducing ramsey/uuid</title>
    <link rel="alternate" type="text/html" href="https://ben.ramsey.dev/blog/2016/04/ramsey-uuid"/>
    <published>2016-04-24T18:00:00+00:00</published>
    <updated>2016-04-24T18:00:00+00:00</updated>
    <id>http://benramsey.com/blog/2016/04/ramsey-uuid</id>
    <author>
      <name>Ben Ramsey</name>
      <email>ben@ramsey.dev</email>
    </author>
    <content type="html">&lt;p class="lead"&gt;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 “&lt;a href="/blog/2014/02/dates-are-hard/"&gt;Dates Are Hard&lt;/a&gt;” post. So, allow me to introduce you to perhaps a familiar face, an old friend, the &lt;a href="/projects/ramsey-uuid/"&gt;ramsey/uuid library for PHP&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Beginnings&lt;/h2&gt;
&lt;p&gt;I’ve been asked on more than one occasion why I created ramsey/uuid. Why was it needed? Why did I open source it?&lt;/p&gt;
&lt;p&gt;It all began with &lt;a href="https://getcomposer.org/"&gt;Composer&lt;/a&gt;. 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.&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;At some point, I stumbled across the &lt;a href="http://docs.oracle.com/javase/6/docs/api/java/util/UUID.html"&gt;Java&lt;/a&gt; and &lt;a href="https://docs.python.org/3/library/uuid.html"&gt;Python&lt;/a&gt; UUID implementations, both of which provide rich interfaces for generating UUIDs. Aside from the &lt;a href="https://pecl.php.net/package/uuid"&gt;PECL uuid&lt;/a&gt; package and a handful of small libraries generating UUIDs with &lt;code&gt;mt_rand()&lt;/code&gt;, I couldn’t find a PHP userland implementation providing functionality similar to that of the Java and Python libraries.&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;What is a UUID?&lt;/h2&gt;
&lt;p&gt;UUID is an acronym for &lt;em&gt;universally unique identifier&lt;/em&gt;. 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:&lt;/p&gt;
&lt;pre&gt;379dae82-5a2b-4c4b-8193-b8e7749a3495
&lt;/pre&gt;
&lt;p&gt;A UUID aims to be &lt;em&gt;practically unique&lt;/em&gt; such that information may be uniquely identified across distributed systems, without central coordination of identifiers. There are 16&lt;sup&gt;32&lt;/sup&gt; possible UUIDs, so it’s highly unlikely that there will be a duplicate. &lt;a href="https://en.wikipedia.org/w/index.php?title=Universally_unique_identifier&amp;amp;oldid=716398107"&gt;According to Wikipedia&lt;/a&gt;, 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%.”&lt;/p&gt;
&lt;p&gt;&lt;a href="https://tools.ietf.org/html/rfc4122.html"&gt;RFC 4122&lt;/a&gt; defines a specific variant of UUIDs having five versions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Version 1 is constructed from the current timestamp and local machine MAC address&lt;/li&gt;
&lt;li&gt;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&lt;/li&gt;
&lt;li&gt;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&lt;/li&gt;
&lt;li&gt;Version 4 is randomly-generated and is probably the most common version used&lt;/li&gt;
&lt;li&gt;Version 5 is the same as version 3, but it uses SHA-1 hashing instead; it is the preferred version for name-based UUIDs&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;What’s In a Name?&lt;/h2&gt;
&lt;blockquote class="epigraph"&gt;
&lt;p&gt;What’s in a name? That which we call a rose &lt;br /&gt;
By any other name would smell as sweet.&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;William Shakespeare, &lt;em&gt;Romeo and Juliet&lt;/em&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you used ramsey/uuid before the 3.x series, you’ll recall that this library began its life with the vendor name &lt;em&gt;Rhumsaa&lt;/em&gt;. 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.&lt;/p&gt;
&lt;p&gt;I received complaints about &lt;a href="https://twitter.com/henrikbjorn/status/302090900052520960"&gt;not remembering how to spell it&lt;/a&gt;. I heard from others who &lt;a href="https://twitter.com/Hipsterjazzbo/status/592059359833694208"&gt;didn’t realize I was the package maintainer&lt;/a&gt;. One developer even encountered a problem and assumed it was a result of my “&lt;a href="https://github.com/ramsey/uuid/issues/36"&gt;GitHub username change&lt;/a&gt;;” they thought I had changed my GitHub username from &lt;em&gt;rhumsaa&lt;/em&gt; to &lt;em&gt;ramsey&lt;/em&gt;, breaking the location of the package in Packagist.&lt;/p&gt;
&lt;p&gt;So, what does &lt;em&gt;rhumsaa&lt;/em&gt; mean, after all? As I wrote in my “&lt;a href="/blog/2013/08/wild-garlic/"&gt;Wild Garlic&lt;/a&gt;” post, “[T]he word &lt;em&gt;rhumsaa&lt;/em&gt; is a Manx word derived from the Old Norse &lt;em&gt;hrams-á&lt;/em&gt;, meaning ‘wild garlic river.’ In English, this word is &lt;em&gt;ramsey&lt;/em&gt;.”&lt;/p&gt;
&lt;p&gt;I was attempting to be clever with my vendor name, and it caused a lot of confusion.&lt;/p&gt;
&lt;p&gt;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 &lt;a href="https://twitter.com/ramsey/statuses/494560272326336512"&gt;asked on Twitter&lt;/a&gt; and opened &lt;a href="https://github.com/ramsey/uuid/issues/48"&gt;Issue #48&lt;/a&gt; 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., &lt;a href="https://github.com/ramsey/twig-codeblock"&gt;ramsey/twig-codeblock&lt;/a&gt;, &lt;a href="https://github.com/ramsey/vnderror"&gt;ramsey/vnderror&lt;/a&gt;, etc.) and then I changed the name of ramsey/uuid for the 3.x series.&lt;/p&gt;
&lt;p&gt;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 &lt;a href="http://mtdowling.com/blog/2014/03/15/guzzle-4-rc/"&gt;the Guzzle project addressed a similar namespace and package name change&lt;/a&gt;. 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.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;When UUIDs Collide&lt;/h2&gt;
&lt;p&gt;Shortly before the GA release of 3.0.0, I received a troublesome bug report. &lt;a href="https://github.com/ramsey/uuid/issues/80"&gt;Issue #80&lt;/a&gt; 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.&lt;/p&gt;
&lt;p&gt;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. &lt;a href="https://github.com/ramsey/uuid/issues/80#issuecomment-144331529"&gt;It began to scare people&lt;/a&gt;, 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.&lt;/p&gt;
&lt;p&gt;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 &lt;a href="https://twitter.com/willemjanz"&gt;Willem-Jan Zijderveld&lt;/a&gt; and &lt;a href="https://twitter.com/ircmaxell"&gt;Anthony Ferrara&lt;/a&gt; in the #phpc channel on &lt;a href="http://freenode.net/"&gt;Freenode IRC&lt;/a&gt;. Willem-Jan pointed us to the &lt;a href="https://wiki.openssl.org/index.php/Random_fork-safety"&gt;OpenSSL random fork-safety&lt;/a&gt; issue, where the OpenSSL project explains:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;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).&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;They go on to say:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;OpenSSL cannot fix the fork-safety problem because it’s not in a position to do so.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;OpenSSL was the culprit. More specifically, the use of &lt;code&gt;openssl_random_pseudo_bytes()&lt;/code&gt; 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.&lt;/p&gt;
&lt;p&gt;Discovering this launched discussions on &lt;a href="https://github.com/paragonie/random_compat/issues/96"&gt;what to do about OpenSSL&lt;/a&gt; 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 &lt;code&gt;random_bytes()&lt;/code&gt; 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.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ramsey/uuid 2.9.0 &amp;amp; 3.3.0 fix the UUID collision issue caused by OpenSSL. All users should upgrade. Thanks! &lt;a href="https://t.co/N6Rwz1a5e2"&gt;https://t.co/N6Rwz1a5e2&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;— Ben Ramsey (&lt;a href="https://twitter.com/ramsey"&gt;@ramsey&lt;/a&gt;), March 22, 2016, &lt;cite&gt;&lt;a href="https://twitter.com/ramsey/status/712357041822687232"&gt;Twitter&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It’s interesting to note that &lt;a href="https://twitter.com/SwiftOnSecurity"&gt;@SwiftOnSecurity&lt;/a&gt; picked up on the issue and posted about it:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Fascinating investigation into developers getting tons of UUID collisions in small datasets (via &lt;a href="https://twitter.com/CiPHPerCoder"&gt;@CiPHPerCoder&lt;/a&gt;) &lt;a href="https://t.co/apEOzx2m3B"&gt;https://t.co/apEOzx2m3B&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;— SwiftOnSecurity (&lt;a href="https://twitter.com/SwiftOnSecurity"&gt;@SwiftOnSecurity&lt;/a&gt;), March 26, 2016, &lt;cite&gt;&lt;a href="https://twitter.com/SwiftOnSecurity/status/713596652192313345"&gt;Twitter&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;3.4.1 and Beyond&lt;/h2&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;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, &lt;a href="https://github.com/ramsey/moontoast-math"&gt;moontoast/math&lt;/a&gt;. 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.&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;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 &lt;a href="https://github.com/ramsey/uuid/issues"&gt;ramsey/uuid GitHub issues page&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/ramsey/uuid/issues/117"&gt;Store UUID in an optimized way for InnoDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ramsey/uuid/issues/116"&gt;Consider supporting version 2 DCE Security UUIDs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ramsey/uuid/issues/110"&gt;Set lowest PHP version requirement to 5.6&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ramsey/uuid/issues/109"&gt;Use a math library other than moontoast/math&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ramsey/uuid/issues/90"&gt;Create DateTime with nanoseconds&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;How To Use It&lt;/h2&gt;
&lt;p&gt;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:&lt;/p&gt;
&lt;div class="code-block" data-lang="shell"&gt;&lt;pre&gt;&lt;code class="language-shell"&gt;$ composer require ramsey/uuid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;div class="code-block" data-lang="php"&gt;&lt;pre&gt;&lt;code class="language-php"&gt;$uuid = \Ramsey\Uuid\Uuid::uuid4();
echo $uuid-&amp;gt;toString();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;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 &lt;a href="https://github.com/ircmaxell/RandomLib"&gt;RandomLib&lt;/a&gt; library as the random generator, you may configure the library to do so:&lt;/p&gt;
&lt;div class="code-block" data-lang="php"&gt;&lt;pre&gt;&lt;code class="language-php"&gt;$factory = new \Ramsey\Uuid\UuidFactory();
$factory-&amp;gt;setRandomGenerator(new \Ramsey\Uuid\Generator\RandomLibAdapter());

\Ramsey\Uuid\Uuid::setFactory($factory);

$uuid = \Ramsey\Uuid\Uuid::uuid4();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;aside class="admonition note" role="note"&gt;
&lt;h6 class="admonition-label"&gt;Note&lt;/h6&gt;
&lt;p&gt;
By default, ramsey/uuid uses &lt;code&gt;random_bytes()&lt;/code&gt; to generate version 4 UUIDs. Since &lt;code&gt;random_bytes()&lt;/code&gt; is available in PHP 7 and up, ramsey/uuid uses &lt;a href="https://github.com/paragonie/random_compat"&gt;paragonie/random_compat&lt;/a&gt; to provide a polyfill for earlier versions of PHP. In most cases, &lt;code&gt;random_bytes()&lt;/code&gt; and its polyfill are sufficient random generators, and unless you have a special case, you should stick with the default.&lt;/p&gt;
&lt;/aside&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;div class="code-block" data-lang="php"&gt;&lt;pre&gt;&lt;code class="language-php"&gt;$factory = new \Ramsey\Uuid\UuidFactory();
$factory-&amp;gt;setTimeGenerator(new \Ramsey\Uuid\Generator\PeclUuidTimeGenerator());

\Ramsey\Uuid\Uuid::setFactory($factory);

$uuid = \Ramsey\Uuid\Uuid::uuid1();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;div class="code-block" data-lang="php"&gt;&lt;pre&gt;&lt;code class="language-php"&gt;$factory = new \Ramsey\Uuid\UuidFactory();
$generator = new \Ramsey\Uuid\Generator\CombGenerator($factory-&amp;gt;getRandomGenerator(), $factory-&amp;gt;getNumberConverter());
$codec = new \Ramsey\Uuid\Codec\TimestampFirstCombCodec($factory-&amp;gt;getUuidBuilder());

$factory-&amp;gt;setRandomGenerator($generator);
$factory-&amp;gt;setCodec($codec);

\Ramsey\Uuid\Uuid::setFactory($factory);

$uuid = \Ramsey\Uuid\Uuid::uuid4();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;hr /&gt;
&lt;h2&gt;Thanks&lt;/h2&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;I want to first thank &lt;a href="https://twitter.com/huizendveld"&gt;Marijn Huizendveld&lt;/a&gt;. Marijn submitted the first pull requests to ramsey/uuid and contributed the Doctrine ORM integration that I later split out into the separate &lt;a href="https://github.com/ramsey/uuid-doctrine"&gt;ramsey/uuid-doctrine&lt;/a&gt; library. It was Marijn’s participation that got me excited about collaborating on an open source project and continuing the work.&lt;/p&gt;
&lt;p&gt;I owe a debt of gratitude to &lt;a href="https://twitter.com/ThibaudAztech"&gt;Thibaud Fabre&lt;/a&gt; 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.&lt;/p&gt;
&lt;p&gt;Most recent, &lt;a href="https://twitter.com/JessicaMauerhan"&gt;Jessica Mauerhan&lt;/a&gt; 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.&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/ramsey/uuid/graphs/contributors"&gt;List of ramsey/uuid contributors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ramsey/uuid-doctrine/graphs/contributors"&gt;List of ramsey/uuid-doctrine contributors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ramsey/uuid-console/graphs/contributors"&gt;List of ramsey/uuid-console contributors&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cheers!&lt;/p&gt;
</content>
    <category term="uuid"/>
    <rights type="html">Copyright © 2016 Ben Ramsey. Licensed for use under &lt;a href="https://creativecommons.org/licenses/by-sa/4.0/"&gt;CC BY-SA&lt;/a&gt;.</rights>
  </entry>
  <entry>
    <title type="text">Hour of Code</title>
    <link rel="alternate" type="text/html" href="https://ben.ramsey.dev/blog/2015/12/hour-of-code"/>
    <published>2015-12-21T00:00:00+00:00</published>
    <updated>2015-12-21T00:00:00+00:00</updated>
    <id>http://benramsey.com/blog/2015/12/hour-of-code</id>
    <author>
      <name>Ben Ramsey</name>
      <email>ben@ramsey.dev</email>
    </author>
    <summary type="html">&lt;p&gt;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.&lt;/p&gt;
</summary>
    <content type="html">&lt;p&gt;It was dark when I pulled into the parking lot of the middle school where I would spend the next hour volunteering for the &lt;a href="https://code.org/learn"&gt;Hour of Code&lt;/a&gt;. 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.&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;“What if I say the wrong thing and turn them off to programming?”&lt;/p&gt;
&lt;p&gt;“What if I bore them, and they think coding is boring?”&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;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 &lt;a href="https://csedweek.org/"&gt;Computer Science Education Week&lt;/a&gt; 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.&lt;/p&gt;
&lt;p&gt;No problem. Winging things is my specialty. So, that’s what I did.&lt;/p&gt;
&lt;p&gt;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 &lt;a href="https://en.wikipedia.org/wiki/Origin_story"&gt;origin story&lt;/a&gt;, so to speak.&lt;/p&gt;
&lt;p&gt;I began with a question: “Who has ever written code?” No one raised their hands, so I pressed on.&lt;/p&gt;
&lt;p&gt;“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.&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;From there, I had them open up &lt;a href="https://code.org/"&gt;code.org&lt;/a&gt; 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.&lt;/p&gt;
&lt;p&gt;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 &lt;a href="https://en.wikipedia.org/wiki/ENIAC"&gt;ENIAC&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Software_bug"&gt;bugs&lt;/a&gt;, and &lt;a href="https://en.wikipedia.org/wiki/Grace_Hopper"&gt;Grace Hopper&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;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:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Don’t spend a lot of time talking. Get the students right into the coding exercises.&lt;/li&gt;
&lt;li&gt;Chances are, the teachers you are working with haven’t been through the Code.org exercises. If they contact you through the &lt;a href="https://code.org/volunteer"&gt;Code.org volunteer site&lt;/a&gt;, they probably think you’ll be prepared to lead the class. So, be prepared to lead.&lt;/li&gt;
&lt;li&gt;Code.org provides teacher notes for each of their exercises. Familiarize yourself with the exercises and the notes.&lt;/li&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;li&gt;Do tell what made you interested in coding and how you got started.&lt;/li&gt;
&lt;li&gt;Tell about the first program you wrote.&lt;/li&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Interested in volunteering for an Hour of Code near you? &lt;a href="https://code.org/volunteer"&gt;Sign up here to have teachers contact you&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;
</content>
    <rights type="html">Copyright © 2015 Ben Ramsey. Licensed for use under &lt;a href="https://creativecommons.org/licenses/by-sa/4.0/"&gt;CC BY-SA&lt;/a&gt;.</rights>
  </entry>
  <entry>
    <title type="text">Yak Shaving Is the Entire Job Description</title>
    <link rel="alternate" type="text/html" href="https://ben.ramsey.dev/blog/2015/11/yak-shaving"/>
    <published>2015-11-30T00:00:00+00:00</published>
    <updated>2015-11-30T00:00:00+00:00</updated>
    <id>http://benramsey.com/blog/2015/11/yak-shaving</id>
    <author>
      <name>Ben Ramsey</name>
      <email>ben@ramsey.dev</email>
    </author>
    <summary type="html">&lt;p&gt;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.&lt;/p&gt;
</summary>
    <content type="html">&lt;p&gt;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 &lt;a href="https://www.docker.com/"&gt;Docker&lt;/a&gt; to &lt;a href="https://aws.amazon.com/cloudformation/"&gt;AWS CloudFormation&lt;/a&gt; to a collection of shell scripts.&lt;/p&gt;
&lt;p&gt;Finally, after asking in #pynash (Nashville’s Python user group) on Freenode IRC, &lt;a href="http://jasonamyers.com/"&gt;Jason Myers&lt;/a&gt; pointed me to &lt;a href="https://packer.io/"&gt;Packer&lt;/a&gt; as a potential solution.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Packer is a tool for creating machine and container images for multiple platforms from a single source configuration.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Packer turned out to be the right tool for the job, but I almost scrapped it, since I ran into a few problems.&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;As I struggled to find a solution for the problem I had with Packer, &lt;a href="http://www.tateeskew.com/"&gt;Tate Eskew&lt;/a&gt; reminded me that &lt;a href="https://en.wiktionary.org/wiki/yak_shaving"&gt;yak shaving&lt;/a&gt; is a part of my job.&lt;/p&gt;
&lt;div class="code-block" data-lang="irc"&gt;&lt;pre&gt;&lt;code class="language-irc"&gt;&amp;lt;teskew&amp;gt; i'd just patch it, then. keep it in a central place so you only compile it once.
         then when it's put into mainline, just switch out the binary
&amp;lt;teskew&amp;gt; either way, it's a pretty simple patch to test and change
&amp;lt;ramsey&amp;gt; ugh… gotta set up an environment just to build packer
&amp;lt;ramsey&amp;gt; &amp;quot;simple&amp;quot;
&amp;lt;teskew&amp;gt; you act like yak-shaving isn't the name of the game
&amp;lt;ramsey&amp;gt; :P
&amp;lt;teskew&amp;gt; hell, it's the entire job description
&amp;lt;teskew&amp;gt; :)
&amp;lt;ramsey&amp;gt; I am not an ops person
&amp;lt;teskew&amp;gt; you are right now :)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I ended up &lt;a href="https://github.com/ramsey/packer/commit/016992bb5dcfdf9a62336ac135725cf0c1487ee4"&gt;patching Packer&lt;/a&gt; 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.&lt;/p&gt;
&lt;p&gt;Yak shaving isn’t just part of our jobs, it’s the entire job description.&lt;/p&gt;
</content>
    <category term="job"/>
    <rights type="html">Copyright © 2015 Ben Ramsey. Licensed for use under &lt;a href="https://creativecommons.org/licenses/by-sa/4.0/"&gt;CC BY-SA&lt;/a&gt;.</rights>
  </entry>
</feed>