Lessons From ConFoo

ConFoo 2016 is over. The past days a huge amount of developers, most of them from Canada but also from the USA, The Netherlands, South Africa, France and quite a few other countries came to Montreal for ConFoo. I know I had a lot of fun, and I surely learned a lot. One of the keynote speakers said on Thursday:

“As you learn, share it”

This is something I've been saying as well, but not doing enough of. So as I sit here (local time 4:42AM and awake because at home it's nearly 11AM) I'll share some of the lessons of ConFoo.

Polyglot conferences are the best

This is an overall lesson and something I've learned before and even say in my Level Up Your Team-talk. Going to a Polyglot conference gives you a fantastic amount of extra information. Just talking to people with different backgrounds will teach you a lot about how other languages solve things, and will give you some additional information on when to choose which tool. While my main weapon of choice is still PHP (and I don't see that changing any time soon), I always feel inspired by seeing how other languages handle things. So get your ass over to ConFoo, DomCode, 4Developers or any of those other polyglot conferences. It is certainly worth it.

We can do so many cool things with technology

On Thursday, I attended the talk "Unlocking Data Trapped in Audio and Video Files" by Keith Casey. Now the stuff he talked about in his talk is not something I've really had to do in any of the projects I've worked on, but the one thing I took away from that talk was: We can do some really cool and crazy things with technology. In his talk, Keith talked about not just converting spoken word into text, but also recognizing emotion, identity and more. We can, in varying forms of correctness, actually do stuff like this already. Isn't that amazing?

I also learned something else: Quite a few companies still don't offer APIs. This is scary.

Go!

Friday morning started (for me) with a talk by Gemma Anible called "When All You Have Is An Elephpant..." which was, predictable, about choosing the right tool for the job and how PHP is not always that. This is a lesson I learned a long time ago, but what made me come to this talk was that Gemma was going to talk about Go. I've been interested in the Go language for quite some time now, but have never really had a reason to actually look into it, so this talk was a great way of at least getting a bit more information about it.

I have certainly come to the conclusion that I need to check out Go. The examples Gemma gave are quite nice. Though a slightly different syntax, I don't think it would be hard to learn the syntax of Go, but the concepts are certainly different, and it's those concepts that make the language quite interesting, especially for running a lot of stuff concurrently (for instance when writing workers that process stuff in the background). Gemma recommended the Go Tour, so I need to check that out soon.

The power of lightning talks

ConFoo ended with lightning talks. Now the lightning talks I'm used to are usually 10-15 minutes long, but the lightning talks at ConFoo were only 5. I was a bit sceptical at first, but this works extremely well. It is amazing how much information one can put into 5 minutes when challenged to do so, and the talks were a nice variation of funny and serious talks. I am seriously considering doing an event in The Netherlands now purely based on lightning talks. If you're interested in this, drop me an e-mail.

Share your lessons

When I decided to try and blog a bit more again, I wanted to try and share more information again. There had been months where I had not blogged, or only blogged once. Looking at my archive I see an increase in blogposts since January 2015, and though there have still been months without blogpost and months with only one blogpost. I will be trying to increase that again. I'm not sharing enough with the world, and I feel I need to improve on that.

While I try, perhaps you should also try. Blog, speak at usergroups, join community Slack channels, speak at unconferences and conferences, tweet, exchange information and knowledge at the office. Share your lessons.


Three Months Of Patreon

Tomorrow it is three months ago that I launched my Patreon page. As I mentioned in my blogpost about launching my Patreon page, it was mostly an experiment to see how that would work out. I've seen a bunch of artists use Patreon very successfully, but the world of PHP, open source and software development, while it has some parallels, is different from the world of art, music and books. I was curious about how Patreon would be received in this world.

Since it was an experiment, any outcome would be a good outcome. I went without real expectations. Of course I was hoping it to be a major success, but with me being the only Patron of Rafael, I wasn't expecting much.

Now, three months later, I have two patrons. I am very grateful to Malte and Rafael for their support. I've promised to only charge them a maximum of once a month, and so far I've charged them twice. This does not mean I get a lot of money. With those two charges, I can now buy me a beer.

We are not used to paying for free content

I found out about Patreon through Amanda Palmer, who successfully uses Patreon to fund music she gives away for free or sells for a very low price. Most of her music is available for "name your price" (basically, $0 or more) on her bandcamp page. Her most recent release, the David Bowie tribute EP Strung Out In Heaven has a minimum of $1, but that's mostly to pay for the royalties she owes the Bowie estate. Yet for every Thing she releases, even though it is available for (nearly) free, she gets paid nearly $34000. I think that's awesome! And it makes sense, because this is her life. This is how she makes her money. From her music.

Through Lorna I found out about an article on A List Apart by Rachel Andrews on the high price of free. In that article, Rachel says some really important things. For instance:

As an industry we have become accustomed to getting hundreds of hours of work, and the benefit of years of hard-won knowledge for free.

This is what open source has done for us, and it is fantastic! If you run into a problem, you're a quick Google search away from finding the solution. If you come by a new piece of tech, most of the times there's already tons of documentation and blogposts on how to work with this tech. This is extremely valuable and one of the main reasons why open source is awesome: There is virtually no barrier of entry to get into programming, aside from the need for a computer and an Internet connection.

While this is awesome, it also means that we've grown accustomed to getting all this information for free. We gladly consume all this labour of love by passionate developers and content creators and expect things to be free. And of course we should, that is why the creators made it. What I do think, however, is that we should consider to show our appreciation a bit more.

We are used to paying for paid content

We consume free content without any problem, and we also consume paid content without any problem. Sure, there is a small problem of piracy for paid content, but mostly people will gladly pay for their php[architect] subscription, their copy of Chris Hartjes' books or one of the many awesome publication of Lorna Mitchell. We seem to be fine with paying for content that has a price on it. This is, obviously, a good thing. The people who create this content spend a lot of time on it and are, partially or fully, depending on the sales of their content for their income. I can recommend you a shitload of content that is very much worth the money (seriously, ask me if you need anything).

So about that free content

We're used to paying for content, that much is clear. So why not show your appreciation of the free content out there by paying for that as well? Patreon is only one way of doing so. Last December, I went into my Steam account and through my friends list, and randomly donated some games from the wantlist of those friends to them. Many content creators also have Amazon wishlists. Sometimes, people also have some paid product aside from their free work. For instance, Jordi has Toran Proxy and an Amazon wishlist. And without wanting to do too much self-promotion, I have a Patreon page and a Paypal page for donations. Derick Rethans also has an Amazon wishlist. And these are just a few examples. If you consume a lot of free content (whether it is code, documentation/blogposts or anything else), please consider showing your appreciation.

Enabling people to show their appreciation

One does not work without the other: If you are a content creator and you supply your work free of charge, please consider adding a way for people to show their appreciation. Whether this is an Amazon wishlist, a Paypal page or a Patreon page, your Steam wishlist or something else does not really matter. What is important is that you enable people to show their appreciation. If more content creators do this, perhaps more people will get used to somehow paying for free content. And those who are less fortunate and simply can't pay will still be able to access all the free content out there.

Let's make one thing clear: I don't expect any content creator in the open source world to start earning $34000 for each piece of content they create, but it would be nice if people could just get that extra bit of money in that may allow them to sometimes just buy an extra ticket to a movie or concert, or that one bottle of whisky they really want. Let's try to change the mindset a bit and allow people to pay for free content.


The Sprint Demo

The new year also brought a new customer for me: At the start of January I started at the Digital Solutions Center of Schiphol Airport. They have an awesome project going on, and I operate in one of the two scrum teams there.

When you're starting with a new customer that has adapted Scrum (or any form of agile), it is always interesting to see how they adopted it. Interpretation and implementation of scrum and other agile methodologies differs greatly amongst different customers. I've had customers where it worked really well, and I've seen customers where scrum was only an excuse to be able to switch priorities or scope whenever they felt like it. No, I won't mention names ;)

Overall Schiphol gets agile. Not just the developers, but throughout the organization you'll see scrum boards in the hallways or in offices. It is awesome to see this work not just inside development teams. But there's one thing I've been most impressed with from the start: The sprint demo.

To give you some context: Just about every scrum/agile project I've worked on in the past had the same form of demo: One person would start in front of a crowd of stakeholders, team members and other interested people and run through the features that were delivered in the most recent sprint. The meetings were usually boring and one-way traffic: There was little interaction because of the way the meeting was set up.

In some projects, this was recognized and stakeholders were encouraged to speak up and give feedback. So now we got feedback, which was good, but the meetings could still sometimes be really boring, or break into useless discussions between stakeholders about implementation details or even worse: internal policy decisions.

Sprint Demo, photo by Paul Nieuwdorp

Schiphol got this and took on a new style of sprint demo. Instead of having a single person present the new stories that were delivered, stakeholders are split up in smaller groups. Several team members work together (or split the group up even more) to present the stories that were completed. Some of the team members present the features while others are standing there with sticky notes to write down any feedback from the stakeholders. Stakeholders are also encouraged to take the mobile devices that are on tables throughout the area to test all of the delivered mobile stories. Throughout the demo, the groups switch to other screens/devices to see other new features. At the end of the demo most people have seen all new features and have been able to give feedback on them.

Sprint Demo, photo by Paul Nieuwdorp

One of the most important reasons to take an agile approach is to have a good, short feedback cycle: To gather feedback from the stakeholders, the business owners, and possibly even your users. By taking this more interactive approach, it is much easier to get good feedback from all parties involved. But it also ensures a good, informal contact between the development team(s) and the stakeholders. Because the groups are smaller and the whole setup is not about one-way communication, people (even team members) feel free to offer their comments, to give that feedback that you as a team need to improve the product and to ensure you build the software according the expectations and wishes of the stakeholders. And that is eventually what the agile approach is about: Building the things that people want, not what they think they want. Because the groups are smaller, there is also less useless discussion. If a discussion happens, it is usally about the new feature and not about internal policies or decisions.

I've found this form of sprint demo to be much more in the spirit of scrum and agile, and I've been impressed at the way both teams handle the demo, and the way it is received by the stakeholders. The feedback we get is valuable and the time we spend on the demo feels well spent.

So have a look at your sprint demo. See how it works right now, and have a good look at how you can improve. The above may not work for every organization, but I sure am impressed how well it works within Schiphol.


Motivating people to learn

Nearly two months ago I wrote a piece about Continuous Learning on the Dutch Web Alliance blog. In that article, I presented a lot of different ways of learning. All these ways of learning are interesting, but if you can't convince your developers to actually start learning, there is little use in having all these options. So in this article, I want to look at how to to motivate people to learn.

The core of learning

There's two things that are extremely important in learning new things:

  • They want to learn
  • You show you want them to learn

Both things are equally important, but the first can be influenced by... you guessed it: the latter.

They want to learn

Without motivation from your team members, they won't learn anything. You can send them to a training and they'll go, but the chance of them actually picking up on something is small. This sometimes has to do with the form of the training (classroom training can be good, but often tends to be boring), and also with the topic. Sending your developer to a training on a framework when they're much more interested in understanding devops, for instance, will definitely not motivate them. They need to want to learn.

You show you want them to learn

As I mentioned before, if your developer has a hard time getting motivated to learn, it really helps if you show them that you want them to learn. Not by forcing things on them, but by starting a conversation about education and the topics they want to learn about.

The Personal Development Plan

A good first step is to create a Personal Development Plan. This doesn't have to be a huge document, and it doesn't have to be very formal. It should, however, document a plan for the personal development of your team member. Document where the developer currently is, where they want to be and how much time they should take to get there. It is nice if there are some steps in the plan on how to get there. These steps could include education, but also other forms of learning (see Continuous Learning).

Keep in mind that this document is only there to guide your team member, the details in this document are not set in stone. Along the way they might find out that perhaps the goals was actually not right, or perhaps the steps were incomplete or incorrect. Things may change along the way, so it is a good idea to have one or more moments of evaluation along the way.

Invest money

Another very good way to show your developer that you want them to learn is to invest in the learning. Most companies these days have a training budget for every team member that they can use, but a lot of companies I've encountered use this mostly for traditional classroom training sessions or workshops. Keep the conversation open as to what they can spend the budget on: While some people may learn best using a classroom training or workshop, others may learn better by doing experiments. Last WeCamp one group of developers started playing with an Arduino and developing something that could talk to the Arduino. Buy your developer an Arduino (or other necessary hardware). Another example: Offering to pay for travel to a usergroup is a small financial investment for your company, but can be the deciding factor between going and not going to said usergroup.

Some people like to learn more about speaking (or knowledge transfer in general, where speaking is just another way to transfer knowledge). Offer them to use the budget to cover any costs for speaking at conferences that the conference doesn't cover. Sure, this is not directly supporting the learning, but those indirect costs can deter someone from making that step into speaking.

The above is just an example, but long story short: Don't limit the budget to traditional education, but keep the conversation open and look at what is needed for your team member to learn.

Invest time

Believe it or not, but developers are just like humans. Although a lot of developers tend to spend a lot of free time on programming and hobby projects, this does not mean they automatically want to use their free time to learn new stuff for work. Offer your developer to attend a usergroup, conference or other event during work hours (or allow them to get the free time they sacrifice back in vacation days). This could well convince your developers to spend time on learning. Since they are learning for their work, it is only fair to let that learning be their work.

If you have the opportunity, start an 80/20 program. Have your team work 80% of their time for the customer, and allow them to have the other 20% for learning, research&development, contributions to the community and open source. From the moment I hired my first developer I implemented this. Don't just let them do everything they want, but discuss possible projects. I can say with a lot of pride that the 20% of both Mike and Jelrik have contributed to:

No, the above is not what Mike and Jelrik learned from it, but working on open source and organizing events has taught them a lot. Not just about technology and programming, but also about planning, communication, even marketing. The 20% time can get your organization a lot more than just education: Our company is listed as sponsor on the phpDocumentor website, mentioned every meetup of PHPAmersfoort as sponsor, and WeCamp is the most epic things ever.

Still no motivation?

Over the years I've sometimes also encountered developers that simply did not want to learn. The conversation is still important, but eventually, if that conversation fails, you should think about why you hired the developer and whether the developer is indeed able to fulfill the role you need from them. If they do: don't force them to learn but just let them to their job. If they don't, it is perhaps time to consider parting ways.

Enable

I love how Rafael Dohms dubbed the term "enablers" instead of "organizers" for the organization of AmsterdamPHP, and I think "we" (whether you are the team lead, tech lead, CTO, manager or whatever you want to call yourself) should be enablers to our developers, not just managers. We should always have an open conversation on the ways people learn best, and support them in that. I am pretty sure that no organization can offer everything that a developer needs, but the best way to determine how and what people should learn is by talking to them. And by keeping that conversation going, motivation usually should not be a problem.


Reduce stress: Focus on what is important

Last Friday I had a great, long meeting with Mike van Riel. There we many things to discuss, but one of the things we discussed was productivity, or rather the feeling of stress you can have even if you shouldn't, and how to counter that.

Mike's done quite a bit of research on this topic (he promised he would publish some of that research once he can), and during that meeting (and afterwards as well) we came up with a couple of lifehacks that would hopefully make our life a bit easier.

E-mail

I have many e-mailaddresses. Many, many e-mailaddresses. While going through my e-mail does not take me a whole lot of time, it can sometimes be distracting. Then again, I definitely need my company e-mailaddress for communication about the project(s) I'm working on, so I can't (and won't) just close my e-mailclient and ignore it for a couple of hours.

A simple change I made, though, was to seperate my Ingewikkeld e-mailaddress from the other adresses by using a different e-mailclient. I now have Airmail for all my personal mail and Thunderbird for my work e-mail. This split up works surprisingly well in removing the feeling of stress because "you have so many things going on". Simple, but effective.

Twitter

On a regular basis, I close my Tweetbot to get some work done. Sometimes it works really well in terms of focus. However, often, Twitter is actually an integral part of my job. Talks I have with people because I've in into a problem, helping other people, or just discussing things to clear my mind off a problem I'm stuck on.

Mike came up with a great question though:

When you look at Twitter, what is most important to you? Is that the order of the columns you've set your Tweetdeck up with?

I had to admit that the columns were set up in the most standard way possible (timeline @skoop, mentions @skoop, timeline @skoopnl, mentions @skoopnl). When I started thinking about it I basically came to the conclusion that tweets by PHPeople were the most important, as well as tweets by some other people that are important. Then the mentions, and after that, my general timeline. Mike suggested I set up my Tweetbot in a way to accomodate these priorities. So this morning, I've sat down to re-organize my Tweetbot to accomodate this. I've created two private lists (PHPeople for PHP-related tweets, Personal stuff for non-PHP people of whom I value the tweets). Those are my first two columns. Then the mentions columns for both accounts, and after that the main timelines.

It takes some getting used to the different layout, but already I notice two things:

  • My main "timelines" (the first two columns) are much slower. I like that.
  • I have a better feeling of not missing out on important tweets

Tweetbot

I'm sure there's more

Sometimes small changes can have a big impact and I've already noticed the impact of these two relatively small changes. Look at the things you do often and see how they can be improved. And if you've found some, feel free to share them as well!


The PHP Developer During Advent

It is December 1st, which is the traditional start of the advent period, the period leading up to Christmas. It has also in the past years sparked initiatives in the PHP, web development and Open Source communities. Some of those initiatives I want to mention here for everyone's enjoyment and education.

24 Pull Requests

To give back to the open source projects we all use on a regular basis, the suggestion of 24 Pull Requests is to send a pull request per day to any open source project. They give you suggestions on the projects and you can of course suggest other projects. It's an interesting challenge to send a PR every day up until Christmas, but if you're up for it, many projects will be grateful.

24 Days In December

During the days until Christmas, this website will post a daily thought on PHP and the community. Add it to your feed reader. Spoiler: I have contributed.

24 Ways

For those that do more than just PHP, 24 ways will give you an article per day on web design and development. Even if you only do PHP, it might be a good idea to broaden your horizon in December using this site.

Advent of Code

If you're up for a series of coding puzzles, you might enjoy Advent of Code. Advertised as interesting for any level developer, you can do a new puzzle every day.

24 Days of Blackfire

To help guide you through "the challenges of managing the performance of your applications", Blackfire is publishing 24 tutorials under the 24 days of Blackfire name.


Launching my Patreon page

In June, I launched IWantTo.Support, a website dedicated to displaying people and projects that you can support. Not just by helping them, but also financially. For a long time I've been thinking about this. While helping a project or developer by coding, documenting or promoting, it sometimes is actually nice to help them by buying them a beer, book or something else they want.

Now I am at a lot of conferences, so every once in a while I can buy someone a beer. I've also on occasion purchased something off an Amazon wishlist to show my appreciation. But not a lot of projects and developers actually allow simply donating some money. I think more people should give the opportunity of donating some money.

Earlier this year I got introduced to the concept of Patreon, which is used mostly by artists (yes, it was through Amanda Palmer that I found out about it). From the moment I heard by it I was intrigued by the approach they take to payments for content and I started wondering out loud if we could somehow use the concept for open source contributors.

So can we?

Yes, we can. And actually, Rafael already did. You can (and should) support him. His approach is one of monthly payments. Every month, you donate an amount in appreciation of his work for the open source community, which includes the hours he puts into usergroups but also the work he does on Pronto!, which is clearly mostly for (aspiring) speakers, but still takes quite some time.

The other approach you can take on Patreon is one where you pay per "thing". This makes a lot of sense for open source projects: They could charge people for each release, for instance. And Patreon protects you as supporter against projects that do a lot of releases, because you can choose a maximum amount of money you spend on a project per month. And of course, the project could simply limit the amount of releases that they charge for. This approach would be perfect for libraries, frameworks but also applications. I would happily support some of the projects I've been using in the past years in this way.

My Patreon

I have also chosen this second approach for my Patreon page. Since I don't release a lot of code, I can't really charge per release of my code. One thing I do on a (sort of) regular basis though is to write blogposts. Whether it is here, on the DWA site or elsewhere, I do write regularly. And while these articles are released for free, it is something people could support. It is an experiment, I have no idea if this will be successful and if it will be, how successful it will be, but let's hope it will work.

I've also added some rewards! When you start with a single dollar, you'll get an e-mail from me. If you donate more than $25 per thing, I will do a brainstorm session over skype or hangout on any PHP-related topic. If you donate over $30, I'll also send you some actual snailmail stuff like a postcard, perhaps some stickers or anything else I might have lying around. Again, it's all an experiment. I'm also very much open to any suggestions you might have to improve the rewards, so do let me know if you have any ideas about this.

Recurring support too much?

If recurring support for the same person (in this case: me) is too much (I can understand that) but you want to do a one-off donation, that is possible too. I've added an about page that contains a Paypal.me link where you can donate.

Accept donations

So, now that Rafael has taken the step to accept donations and I have taken the step to accept donations, will you? I would love it if more people would take the step of accepting donations, either one-off or recurring. Even if you only get a single donation. Even if you get no donation. If you don't try, you won't get anything anyway.


Migrating Octopress to Sculpin

Just over a week ago I wanted to publish my previous blogpost, only to find out that the Gist plugin I was using for the code samples didn't work anymore. Some research showed me that the something changed in the way the Gist API worked that warranted an upgrade of the plugin. So I thought I'd quickly update the plugin to make it work again. Instead, I completely broke my Octopress install. Any attempts to revive it failed big time, partially because of my lack of knowledge regarding Ruby and the gem system.

I considered my options. I don't know much about Ruby or gem, so digging into that, while it would teach me something, would take quite a while. Then of course, I've done some work with Bolt recently, so I could migrate to that. That would still be quite a bit of work because Bolt would have to use a database. Given my recent adventure with Sculpin and the fact that Sculpin out of the box nearly supports the format Octopress is using, I decided to migrate to Sculpin instead.

The migrating to Sculpin was actually nearly painless. There were a couple of small issues I ran into, and I'm documenting them here for anyone else attempting to do the same thing.

Twig code snippets

Since Sculpin is actually using Twig templating engine to generate the pages, having Twig code snippets in your blogposts is going to cause some issues. I solved that by adding the verbatim Twig-tag around the code samples, inside the triple-backtick codeblock seperator. I did look into installing the codeblock plugin, but decided in the end that it was overkill for what I was trying to do.

Categories

In Octopress I specified categories as a space-seperated list in my header. So it looked like this:


categories: php octopress sculpin

Unfortunately Sculpin did not understand this syntax. Instead, it wanted me to give a yaml-like list:


categories:
  - php
  - octopress
  - sculpin

Although this looked like a small change, because I have my full blog archive since 2004 on this site, I had to update all these. For a bit I considered automating this change, but I decided against that and simply went through all of the old articles to update this. Not the most fun job, but it actually made me realize the amount of stuff that is in here. It was fun reading back some of my old blogposts and realize how much I have learned since those days.

There may be other problems

There may of course be other problems with the migration if you're using other options in Octopress that I wasn't using. And as you can see, at the time of writing this, I haven't actually applied a theme yet to the new Sculpin installation. This is something I still need to work on. For now: It works, I can blog again. Yay for Sculpin!


Creating a Bolt theme from a template

A friend recently asked me if I could make a simple website for the new radiostation he was joining as a DJ. My usual job is big applications and web projects, so (while this may sound weird) a simple website is actually something I'm not that efficient in, but since finding Bolt I actually do that every once in a while. Setting up and configuring Bolt is such a simple task that I've been happily creating some simple websites for friends or contributing to website projects every once in a while.

My main weak point is frontend and design. This is something I have been painfully aware of for ages already. Luckily there are sites like TemplateMonster and Open Source Web Design that offer templates that can be used for websites where there is no dedicated designer/frontender, nor budget for one. After a quick talk with my friend there was some budget to get a paid template from TemplateMonster, but now this template needed to be applied to the Bolt installation I had set up and configured with the required contenttypes.

The thing with Bolt is: It's actually quite easy to create themes. One of the reasons is the fact that they use Twig as a template engine, but on top of that they've added some pretty nice and useful extensions. So, let me walk you through the steps I took to create the theme for this specific site, which is my usual workflow for creating a Bolt theme.

The directory structure

Bolt's themes can be found in the /theme folder, which is quite obvious. By default, Bolt comes with two standard themes: default and base-2014. These are very helpful, because they give you a good idea of the structure and approach you can take in creating the templates. But since it's Twig anyway, if you want to use another approach, that's not that hard.

To create a new theme, you create a new directory in the theme directory with a name that represents your theme. In my case, I created the directory /theme/atlantis.

Assets

Next up: Assets. Any stylesheets, javascripts and images can be put into the newly created directory. You could put them somewhere else, but it's obviously easier to keep it all in the same directory, especially since Bolt has some additional variables available in the templates such as paths.theme, which you can use in your templates to refer to the base theme directory (we'll talk about that later). I took the js, css and images directories from the design I purchased and put them in /theme/atlantis directory.

Switching the active theme

Another thing I need to do is to switch the active theme before I can actually test my work. For this, I need to open the app/config/config.yml file and update the theme value:


    theme: atlantis

Now Bolt will look for the template files in my theme/atlantis directory.

Breaking up the design

In most websites, every page consists of several parts. Some parts are very specific to the page you're viewing, others are shared throughout the site. For instance, the header and footer, sometimes also the sidebar. In this case, the header and footer are used throughout the site (except for the homepage), and only the middle part is different for different pages. So the first thing I needed to do was identify which parts of the HTML could be shared and put them into different template files. Luckily, the template I purchased was well documented and easily marked the "cut lines" for the header and footer. Pretty quickly, I had a _header.twig file and a _footer.twig file.

As usual, the header contains a lot of links to css files and javascript files. As I mentioned before, Bolt adds some useful variables to your templates that can be used to make sure the URLs you use are always correct. Imagine your template being renamed, or put into a subdirectory when you go live, if you use hardcoded URLs such as /theme/atlantis/js/jquery.js, this won't work anymore when the site is being deployed on production into /radio. Bolt's paths variable comes to the rescue.

So I went through the header to create relative paths for this. Just to give you an idea, this is part of the header now:


    <link rel="icon" href="{{ paths.theme }}/images/favicon.ico" type="image/x-icon">
    <link rel="stylesheet" href="{{ paths.theme }}/css/grid.css">
    <link rel="stylesheet" href="{{ paths.theme }}/css/owl.carousel.css"/>
    <link rel="stylesheet" href="{{ paths.theme }}/css/style.css">
    <script src="{{ paths.theme }}/js/jquery.js"></script>
    <script src="{{ paths.theme }}/js/jquery-migrate-1.2.1.js"></script>

For any images that are part of the theme, I did the same thing. I did this for the header and the footer (though the latter contained only two paths that I needed to update, so that was quite simple).

The main pages

The header and footer parts of the template are the same for each of the different templates that the purchased design defined, with the exception of the homepage (we'll get back to the homepage later). However, the content parts were different. That makes sense, because a DJ listing simply looks different from a news section. So from the HTML files I got with the purchased template, I took everything between the header and footer markers and pasted that into a new file. For instance for the DJ section, I created a new file called djs.twig for the listing and dj.twig for the detail page. Now, however, I'm not done yet, because I don't have the header and footer yet. Luckily, we can use Twig's include functionality for that. So at the top, I added:


    {% include "_header.twig" %}

And at the bottom, the predictable:


    {% include "_footer.twig" %}

In the contenttype configuration in app/config/contenttypes.yml, I can now point Bolt to these new templates and make Bolt use those for the dj contenttype, by specifying the templates:


    record_template: dj.twig
    listing_template: djs.twig

Now when I load up the djs page on http://localhost:8080/radio/djs (I use the built-in webserver of PHP to run this website locally using the following command: php -S localhost:8080 -t .), I get the page I just created. However, there is no dynamic content yet in my listing page, because I haven't actually created the dynamic content. It's the just default listing that the HTML file contained. Let's work on that next.

Dynamic content

In the static HTML of the djs.twig, I identified the snippet of HTML that I needed to repeat for each of the DJ's. It was a pretty simple piece of HTML. I quickly filled it with the placeholders for the content that should go in there, which resulted in the following snippet:


    <div class="grid_3">
            <div class="event">
                <img src="{{ thumbnail(dj.image, 270, 170) }}" alt="{{ dj.name }}"/>
                <h6 class="color_2">
                    <a href="{{ dj.link }}">{{ dj.name }}</a>
                </h6>
                <p>{{ dj.teaser }}</p>
            </div>
        </div>

In a Bolt listing page, the records in the database for the specified content type are always available in a variable called records. So surrounding the above snippet is a simple for-loop:


    {% for dj in records %}
        // snippet
    {% endfor %}

Now it actually works, and I get content from the database instead of the static HTML that I had. Yay!

For the record-page which shows the individual DJ (when they click on the name in the listing), I now have to do a similar thing. This page contains a record variable instead of a records variable, which is just a single record, so I don't need a for loop, but the process of making it dynamic is similar as above.

More dynamic content

When you look at the bottom of the DJ listing you'll notice two blocks of text. I could add those statically to the website, but if I were to do that, for every change to that text the radiostation would have to either edit the template themselves or content me. Instead, I wanted to make these blocks of text editable through the Bolt CMS interface. Bolt has a great system of fetching content when you need it. I've put that system to good use for the blocks on the DJ-listing as well as various other dynamic blocks throughout the site.

I've created a new contenttype called blocks for this reason. By creating this contenttype, the CMS backend contains a management interface allowing the radiostation to update the text without having to edit any files. But now I still have to display it in the site. This is where Bolt's fetching content feature comes in.

There are two blocks at the bottom of the page, so I'll fetch those blocks seperately in the location where I want them. This results in the following template code:


    {% setcontent block = 'blocks' where { identifier_string: 'djs_wie_zijn_wij' } returnsingle %}
    <h4 class="color_2">{{ block.title }}</h4>
        <div class="box3">
            {{ block.body }}
        </div>

The first line actually does all the magic. It sets the value of the block variable to the result of a query where I look for a record with the string 'djs_wie_zijn_wij' in the field 'identifier_string'. Because I added the returnsingle parameter it will return a single record. If I didn't do that, it would be an array containing a single record, which is kind of useless. Now, after setting the value, I can simply echo the title and body of the block in the template. I do the same for the second block, just fetching the content by a different identifier_string.

Repeat

Now that I've done the first section (DJs) the same thing can be repeated for the other sections as well. Since all sections except for the homepage use the same header and footer code I can easily re-use those by using the same include systements that I've used in the DJ section. Once I've done that, all I'm missing is the homepage!

The homepage

The process of getting the homepage up and running is actually very similar to what I've described above. I set it up slightly differently though. Because I don't have to reuse the header and the footer of the homepage (the homepage is the only page with this style) I don't have to create seperate header and footer templates, I can simply put it all into one file. I've called that file homepage.twig.

In the app/config/config.yml file I can define what the homepage should contain and which template it should use. This basically defines what information will be available in your template. I've configured the homepage to be:


    homepage: over/homepage
    homepage_template: homepage.twig

This means it's going to use the record from the 'over' contenttype with slug 'homepage'. My 'over' contenttype is used for a section of pages with information about the radiostation (the Dutch word 'over' translates to 'about' in English). The page with the slug 'homepage' clearly contains the information I want to display on the homepage.

Aside from the basic information for the homepage, I also want to display the most recent 5 newsitems, so I manually fetch that content and loop over it.


    {% setcontent latestnews = 'nieuwsberichten/latest/5' %}
    {% for news in latestnews %}
        // the content to display the newsitem here
    {% endfor %}

Now when I load my homepage, it also works!

Getting rid of more duplicated code

Actually, there is still more duplicated code in my templates. Using more include statements, I can easily get rid of that. But since the process of doing that is the same as what I've done with the header and footer, I won't describe it in more detail. Be pragmatic about extracting duplicated content though: Extracting every single detail into a seperate template file and including it wherever it is used can be a pain in the ass once your website enters maintenance, because you'll be searching for ages to get to that specific element that is causing problems in your site. Use your common sense to determine whether you want to extract something into a seperate template, and do it mostly for very common elements such as header, footer, sidebar and navigation.


PHP NorthWest 2015

As you may not have noticed already, I have been accepted to do the closing keynote at the fantastic PHP NorthWest 2015 conference. I am really happy to have been accepted, as this keynote is a personal message from me that I think is important to communicate. In my keynote "Developers Are Just Like Humans" I will be looking at how we as developers may have similar problems as humans and perhaps could solve them in a similar way. It is good to be aware of this.

As with previous years of PHPNW that was accepted as a speaker, I had already bought my ticket for this year's edition of PHPNW. This means I will once again be able to give my ticket to someone. I would prefer to give my ticket to someone who would not otherwise be able to attend PHPNW: A student, someone without a job or who can not otherwise afford to buy a ticket, someone who has not yet been introduced to the PHP community. Please note: I am only giving away a ticket to PHPNW; travel and hotel need to be arranged by the person getting the ticket.

Are you someone who fits the "would not otherwise be able to attend PHPNW" description? Or do you perhaps know of someone that fits the description? Send me an e-mail: stefan@ingewikkeld.net with subject line PHPNW15. I will look at all the e-mails and contact the person I (random or otherwise) decide to give the ticket to.

I am looking forward to PHPNW!