Create A WordPress Site With Lando

For local WordPress and Laravel development, I tend to use a Docker-based solution, most of the time. Depending on the project, I either use Lando or docker-compose. This post is about Lando.

Lando, is no DesktopServer. DesktopServer gives you a simple GUI for creating WordPress sites. Lando has no user interface, you do everything from the command line. That’s good or bad, depending on what you need.

This article explains how I create new sites for local development using Lando. You can see my current .lando file that I use for Caldera Forms development here.

Create The WordPress

Initialize lando in current directory:

lando init --recipe=wordpress

Add a WordPress:

wp core download

That downloaded WordPress core and setup wp config to match Lando’s default variables:

wp config create --dbname=wordpress --dbuser=wordpress --dbpass=wordpress --dbhost=database --skip-check

Add xdebug and MailHog and phpunit

Optional step, but it’s best before going further to add phpunit, MailHog and xdebug. MailHog intercepts all emails coming from the application and provides a webmail-like UI for reading the caught emails.

I love xdebug, I can’t imagine PHP development without it.

In order to run tests “The WordPress Way” you need phpunit installed globally. I disagree with this approach, but Lando makes it pretty simple to do, so fuck it. Here is a .lando.yml file that adds all of these things:

name: formcalderas
recipe: wordpress
config:
  env: dev
  xdebug: true
proxy:
  mailhog:
    - mail.formcalderas.lndo.site
services:
  appserver:
    composer:
      phpunit/phpunit: '*'
  mailhog:
      type: mailhog
      hogfrom:
        - appserver
      portforward: true

Build Containers And Start the site

lando start

This builds the new site and then shows URLs for the site.

At that point you have a WordPress at the URL listed for “APPSERVER URLS”. Click the https link and then finish installing WordPress through the UI. Alternatively use wp cli.

Chrome will not trust the SSL certificate. I normally just click the “Advanced” option and then tell Chrome to trust it. There is a better way to handle this documented here.

Path Mappings For xdebug In phpStorm

In phpStrom preferences go to Language & Frameworks > PHP > Servers and select the current server. Map the root directory to /app

Use It With Bedrock!

Bedrock, along with the Sage Framework is a great option for WordPress app development. Here is a guide to using Lando with Bedrock.

Also Great For Pantheon!

This article is about setting up local sites for general plugin development. We also use Lando for local development of the Caldera Forms site. CalderaForms.com is hosted on Pantheon. We git commit the Lando config file in the repo for the site. That way we have a shared environment and can pull database and file changes using Lando’s CLI, thanks to their Pantheon integration.

Learn more about Lando + WordPress here.

A Listicle Of Laravel Nova Related Blog Posts

This is my list of all of the useful articles I found while experimenting with the Laravel Nova. I will update it with more links as I go.

Laracon 2018 keynote, announcing Laravel Nova.

Nova Packages

Nova Tutorials

Nova Related Links That Do Not Fit In the Above Categories

Customizing the Nova dashboard theme.

Some Quick Thoughts On LoopConf

I was super lucky to be able to attend LoopConf last week. Ryan Sullivan and his team put on an amazing conference. I’ve never been to a fancy developer conference before, and I had a blast. Thanks Ryan for having me! I just wanted to share a few observations about what made LoopConf special and share my recommended videos playlist.

Before I go on, I should point out that while I don’t usually stay in hotels when I travel — I prefer AirBnB –Me and Roy Sivan being super classy by hotel fireplace– the Little America hotel in Salt Lake City where they put us up was classy AF. I didn’t know what to do with myself in such a big fancy room, but I super enjoyed sitting by the fire in the lobby and being classy.

One side of the fireplace had statues of dogs. The other side had a painting of wolves howling in the snow. Apex Classy.

Our REST API Workshop And Something New

Caldera Learn BannerRoy Sivan and I gave a 6 hour workshop on using AngularJS and the WordPress REST API. Honestly, we were worried we couldn’t fill 6 hours, but we actually ran out of time at the end. We had almost 40 attendees and people seemed to get a lot out of it.

I have embedded our slides below, and we also put all of the example code to Github. There is a ton of practical examples in there, some not finished to provide a start point for your own work. Some examples are running live on CalderaForms.com right now.

If you’re wishing you could attend an in depth workshop about the REST API from Roy and I too, don’t worry. We recently announced Caldera Learn. This new site will offer live webinars, recorded courses and code communities for anyone looking to level up their WordPress development skillset. It’s going to be awesome.

The Main Event

Photo by:  Anna Anikina

Our workshop was the day before the main event. LoopConf was a single track conference with excellent talks. They also did a great job of accommodating the hallway track. The room that meals were served in was open all day with the live stream playing. This was a great way to network and watch the talks. I wish WordCamps would do this.

The talks were a lot more focused on philosophy of code, then code. Not that there were not code examples. I really liked this trend for non-workshops.

For example, KAdam White talked about why the WordPress REST API was important for JavaScript developers and why he built his node.js client for the REST API, before showing code for a React app using both tools. Similarly, Natalie MacLees and Nathan Tyler shared their experiences learning React. They provided tons of React and general JavaScript resources in context of using the WordPress REST API.

John Jacoby Jones (JJJ) didn’t really show any code at all. Instead, he talked about lessons from Unix Philosophy that could be applied to WordPress. Andrew Norcross talked about improving our community by acknowledging and dealing with unacceptable conduct that happens in our community.

All the nerdy talks on how to code something or why to code something a certain way were book-ended by business-focused keynotes. Josh Koening of Pantheon talked about how the web has trended away from open source recently as companies have packaged what we created for the open web  in better experiences. He made an excellent point that most people can’t afford what free software costs — time and education.

Jason Cohen of WPEngine spoke about building a bootstrapped business. While he talked about pricing and product design, the best part of his talk was about managing yourself. This especially rang true for me when he talked about focusing on 2xing revenue over shiny features.

I’ve been working on both, and beating myself up over not delivering all the shiny new features I want for Caldera Forms. Those would be done if I wasn’t also working on a new tool that we’re testing right now. Then again, February is looking like a 1.5-2x growth for us versus January, so yah.

I really appreciated both of their talks and spending time talking with both Jason and Josh during the event. I was imagining LoopConf would be all out nerdy-codefest with out a ton of networking. But I got both.

Next Generation WordPress

Photo by: Alexey TopolyanskiyIn 2014 I went to WordCamp Milwaukee and saw two talks on the future of WordPress. Ryan McCue and Rachel Backer presented the beta of the WordPress REST API and Andrew Nacin talked about the WordPress REST API and the WordPress fields API being the basis for a modernized WordPress.

I was super-excited for the vision they shared, and got on the REST API bandwagon pretty hard. Of course, things turned out a bit differently then we expected then. At LoopConf Ryan gave a talk called “Next Generation WordPress”.

He talked about going from the blog era of WordPress, to the CMS era of WordPress and now the platform era of WordPress. Echoing what Matt Mullenweg said in the State of the Word about what got us here is not going to get us where we are going, Ryan suggested a new direction.

While State of The Word was all about user experience, Ryan talked about developer experience. I loved this obviously, as there is a reason I prefer to develop most things in Laravel than in WordPress these days — the developer experience — there has to be a balance here.

WordPress is a user-centered platform and that should never change. But, for users to get an improved experience, both from core as well as plugins and bespoke sites, we need to make it easier for developers to fit those needs. Ryan is, per usual a man with a plan. Definitely watch his talk, do what you can to contribute and let’s hope he gets a reasonable fraction of what he’s asking for there.

Vegan Food, Also Videos

I didn’t expect their to be such excellent vegan food in Salt Lake City, but I was impressed. If you’re ever in Salt Lake City, which I recommend strongly, check out The Vertical Dinner.

I’m still working my way through videos of talks I missed, but I created a highlights playlist from both LoopConfs for you. Check it out:

 

Fun Challenges With Recent Caldera Forms Updates

cropped-CalderaWP_Icon_512x5121.pngLast week, we release a new version of Caldera Forms and a new form translations add-on for Caldera Forms. These were both fun projects to work on and I wanted to share a more technical overview of some of what I did on those projects than I gave in the official release post.

I hope this post is interesting and useful to all WordPress developers, whether you are a Caldera Forms user or not. But if you’re not, maybe it’s time to try it 🙂

https://calderawp.com/2016/11/caldera-forms-translations-and-more/

 

Caldera Forms Translations

Photo by: Ben MoorePreviously, When using Caldera Forms or most other form builders on a multi-lingual site, you had to have to create multiple forms, one per language. That is a pain to manage. Making one change meant editing multiple forms.

Caldera Forms Translations is our new translations add-on. One forms, many languages. I originally was planning this as a feature of the core plugin since we didn’t want to make it a paid add-on. That said, figuring out if a form has translations, then if each field has a translation, and then if that translation is in the right language introduces a bit of overhead to form rendering.

It’s not that much, and its worth the trade-off in exchange for the functionality. But this is one of those features that is great for certain users and not worth it for many, so an add-on makes perfect sense.

The interface for this plugin was a lot of fun to build. It’s actually the first time that we’re using the new Caldera Forms REST API. I will be blogging more about the challenges of implementing the WordPress REST API in a legacy project soon.

I actually did the first pass at this plugin using admin-ajax. I thought it was just going to be one ajax action I need for the admin UI. Turned out I needed three.

You can see the commit where I deleted those callbacks here. But I can best summarize how messy things become validating and authenticating these type of HTTP requests get with this:

if( cf_translate_can_translate() ){
        if( ! empty( $_POST[ 'language' ] ) &&  ! empty( $_POST[ 'form_id' ] ) && ! empty( $_POST[ 'fields' ] ) && is_array(  $_POST[ 'fields' ] ) && ! empty( $_POST[ CF_Translate_AdminForm::nonce_field_name() ] ) ){
            if( CF_Translate_AdminForm::verify_nonce( $_POST[ CF_Translate_AdminForm::nonce_field_name() ] ) ){

That’s terrible and doesn’t even get into sanitization. I think it was the third time I had to refactor that when I decided to add the Caldera Forms REST API infrastructure to Caldera Forms 1.4.4. Previously I had infrastructure and some implementation on the 1.5.0 milestone.
The REST API routes for this plugin has three endpoints. One is for saving settings. The other two are for adding and saving languages.

This add-on supports more than a hundred languages. I don’t want each field to by default to support all of those languages. So, in the UI, there is a selector for languages and an add button. This makes an API call to get the field data, and insert it into the local variable that tracks the languages of the form.

The JavaScript for this interface is a bit experimental and doesn’t use our normal UI framework. I’m playing with new ways to build UI. This add-on was an experiment in using a more structured system. I ended up with a pretty modular system that separates each part of the UI into its own closure. That’s good, because I will probably replace each part one at a time as I continue to use this add-on for experimenting with UI systems and figure out which JavaScript framework we will use in the future.

I will admit that some of this modularity was a bit of overkill and I definitely broke some of my self-imposed rules in order to finish it. Still, I think it would take minimal refactoring to pull one part of the system out if I wanted to replace it with something else, or reuse it elsewhere. Also, it works, which is the point.

One thing I am very happy with is how the class that handles translating fields during rendering works. You can read the source here. This class is a good example of using dependency injection — it takes the form configuration through its parent’s constructor — and using inheritance to create a reusable system. Its parent class is a system for conditionally adding a filter. I might add a similar system to Caldera Forms itself, I’m not sure yet.

Caldera Forms 1.4.4

Photo by: petradr

The new version of Caldera Forms is mainly a bug fix release, with a few enhancements. Most of the bug fixes were to resolve accessibility issues, as we continue to work towards our goal of being the most accessible WordPress form builder. Mainly the new improvements are infrastructure for add-ons and custom development. The REST API infrastructure will get its own post soon.

The biggest improvement in this new version is how file and advanced file fields handle uploads. One of the trickiest thing about building a form builder is dealing with the fact that most form submissions use more than one HTTP request. A validation error means another request may be made. Also, our advanced file field uploads multiple files via multiple AJAX requests and then the main submission happens.

As a result, when the main submission is being processed for a form with an advanced file field the $_FILES super global is empty. These fields allow for saving files to the media library and/ or attaching the files to an email.

If both options are selected, that’s easy. We upload the file to the uploads directory, add it to the media library and then attach that file to the email. When the file needs to be attached to the email, but not saved to the media library, that’s where it gets tricky. The file needs to be saved to the server so it can presit between sessions, but users are right to expect the files to not stay there forever. That creates a privacy issue and disk space usage issue.

My solution for this scenario, which is based on a conversation I had with Micah Wood when we had dinner last time I was in Atlanta, was mainly written in my my car as my wife and I drove back from Atlanta. I introduced a new class to Caldera Forms for handling file saving and implemented it in the existing callback for file fields.

This new class manages files on the server and introduces a concept of a private file. Private files are stored in an almost randomly named sub directory of the uploads directory and deleted later. That dub-directory names is named using a hash that can be created predictably, but only by the server, not an outside observer. As a result I can find the directory later and delete it.

Choosing when to delete that file is also a challenge. It should be deleted after form submission, but it needs to be available when the email is sent, though that email may be disabled. In addition, I had to account for files uploaded to form submissions that failed validation, and were never completed.

So, I wrote two ways to delete it. The first was to set a single CRON to delete the file(s). If form submission is successful, the files will be deleted by the time it runs, but its a good fallback. The other method hooks in at the last action that would be run if no email is set. It checks if the email should be sent. If not, it deletes the files. If an email should be sent, it adds a hook to run after the email is sent, to run basically the same callback.

Read The Source Luke

I hope you found this article useful and that you dig into the source code I’ve shown. Reading the source is the best way to learn.

Writing articles like this is something I’d like to do more of because most of my articles on development are a bit divorced from the real world. That’s fine, I’m teaching a principle most of the time and contrived examples are needed.

The real world is a lot messier than a tutorial. Improving a large code base and fixing bugs without breaking more than 30,000 websites running that code is a challenge. It’s a lot of fun, and its a great way to learn.

 

Getting Started With Modern WordPress Development: What You Need

I’m teaching a few workshops this month aimed at those looking to level up their WordPress development chops. It’s got me thinking a lot about what you need to do quality WordPress development.

It’s a very subjective question, what software to use, what principles to value, what resources to learn from… So I wanted to share my thoughts on what is necessary for getting started. The list is less about software, and more about concepts because in the end, it’s about the wizard, not the wand.

Tools

You can write code in notepad and FTP it up to a shared host and hope for the best, but to do it right you need some basics tools. Here is my opinionated list. I’ve broken it down into “basics” and “important”. The first category is things you should have right away. The second list is important, but can probably wait.

Basics

Code Editor and IDE

A code editor is a specialized text editor designed for writing code. I like Atom as my simple code editor. It’s the application I use when I just need to open up a file, read it and maybe make a few changes.

An Integrated Development Environment (IDE) is more than a code editor. A good IDE provides everything you need to develop in a language. I do most of my work in phpStorm. I use it as a code editor, web server, terminal, sFTP client, Git client, and more. I probably don’t use half of its features.

Git and A Git GUI

Github Social CodingYou must use version control. It’s just not optional if you need to do anything large in terms of development or work with others. It will also be a part of your deployment strategy.

I wrote more about why you should use Git on the CalderaWP blog. WP Pusher, which is an excellent tool for deploying Git repos as plugins and themes, offers a Git course on their site that is worth checking out.

While I use the command line and phpStorm for Git most of the time, I am still a big fan of SourceTree and it’s one of a few reasons I miss using a Mac for my primary development machine.

Local Development Environment

Installing A Site With DesktopServerThe reasons to use a local environment are numerous. The short answer is — it’s faster, more secure, and no one can see your fails.

There are a lot of ways to set up a local environment on your computer.  Here are the ways I recommend, in order of ease of use:

  • DesktopServer – A simple application that gives you an interface for creating local WordPress sites. Start here if you are new to local development. It’s easy and might be all you need.
  • Valet – Made by the Laravel project, but works with WordPress. I use this on my Mac (never figured out how to get it to work in Ubuntu.) Requires Composer, homebrew and a bit of setup.
  • Vagrant – Vagrant creates a virtual machine on your computer that you can use for development. I use the popular VVV project for setting up a WordPress development environment on my main computer.

Important

Dependency Management Tools

Mandelbrot FractalI’m going to go less in depth here, as I’ve covered Composer quite a bit here and on Torque. Seriously use Composer, it makes PHP development better and easier.

Other tools I use for dependency management and task running:

  • Composer
  • NPM
  • Grunt
  • Bower

xDebug

When doing JavaScript development, you can use the browser’s developer tools to debug your code. You set a break point to stop execution and see what the variables equal at that point.

xDebug gives you that for PHP. It’s an amazing tool that takes the guess work, and the vard_dump()/die(); out of development. xDebug comes pre-installed in VVV and works great with phpStorm.

Concepts

Basics

Photo by: veeterzyIf you’re brand new to development, you need to get PHP and JavaScript fundamentals down first.

I’ve written a ton on PHP over on Torque. I recommend starting with my PHP fundamentals article and then looking at my article on using WP_Query to learn object-oriented PHP.

For JavaScript, I like CodeAcademy’s JavaScript course. The book “JavaScript The Good Parts” is also worth reading. Like most WordPress developers, I started with JavaScript by using jQuery and starting in jQuery being a smart start is the consensus we came to when we discussed this on an episode of The WPCrowd, which I followed up with an article on the same topic on Torque.

The WordPress Way

It’s hard to define the WordPress Way, without jumping into WordPress code, which you totally should do. The best way to learn after all is to read the source.

In addition, you really should read the WordPress handbooks:

If you take one lesson from the handbooks, it should be that there is a standard for documenting code and that you should follow it. Inline documentation makes it easier to work with your code, it makes it easier to read your code and it’s super useful to developers who are not familiar with your code.

Principles

I am very much a believer that pragmatic adherence to certain principles will make you a better developer. At a minumum, I think you should familiarize yourself with the single responsibility principle and the do not repeat yourself (DRY) principle.

Class Autoloaders

I’m a huge beliver in using a class autoloader. It’s becoming more common in WordPress, but is still behind. I covered using a PSR-4 autoloader and Composer’s autoloader in an article for Torque.

An autoloader is simple to setup and it forces a logical directory structure and class naming system on to your plugin or theme.

The WordPress REST API

As you probably know, I’m a huge advocate of the WordPress REST API. I think it’s super important for advancing the quality of code and end-user experience we can deliver.

I’ve written a ton on the REST API to help you get started. But, in my mind, it’s not just about learning the REST API. It’s about learning how to write plugins, themes and site-specific code that can be used with theme templates, shortcodes and the REST API.

TL;DR

Photo by: Paula BorowskaPaula BorowskaOk, that was a little long, but here is my summary:

Use local development (start with Desktop Server) and Git (Github and SourceTree FTW.) Composer and autoloaders are awesome. Read Carl and Tom and document your code.

I’ve linked to a ton of free content, mainly by me, to help you learn. I have two WordPress development courses. One on the WordPress REST API and one on modern WordPress development. You should check those out if you want to learn more and say thanks for all the articles and WordCamp talks that I’ve done to help educate the community.

Deploying WordPress Plugins and Sites Built Using Composer

I’m a big fan of Composer, which I believe will give you super powers. I am happy that it is gaining in popularity in the WordPress world. I often hear from developers who love it, but are not sure what to do about the vendor directory in their plugins or themes or sites.

I spoke about the advantages of challenges of using Composer in a recent episode of The Plugin Architect podcast. I use Composer in most of my plugins. Most of Ingot’s code is in Composer packages, which helps us share code between different versions and add-ons. I also helped refactor the plugins Maps Builder and Maps Builder Pro by WordImpress to make sharing code between the pro and free versions easier.

Often times people are not sure what to commit or gitignore and the best way to deploy their code to keep their package size small. I’d like to answer a few questions to help you make the best of Composer for WordPress development.

Should You Ignore The Vendor Directory In Your Git Repo?

TL;DR yes.

A lot of people are hesitant to gitignore the vendor directory and other dependencies in their GIT repos. Most of the managed hosts encourage you to use GIT to manage your dependencies when using GIT as a deploy tool. This is not good practice for  a few reasons.

First, it is messy and redundant. Why should I use a GIT to manage changes in code that is managed by a different VCS system? It doesn’t make sense. A change to a dependency should require a commit in the configuration file for Composer, Bower, NPM, etc, but not commits of actual code.

Also, keep in mind that by default, Composer checks out all packages as GIT repos. That’s great in development, but not something you want included in your final product. Composer is built with this in mind. But you should not ship your plugins with Composer packages as GIT repos or push GIT repos of dependencies to your site.

Down with redundancy and bloat, folks.

Solutions

TL;DR –prefer-dist

Let’s talk about two scenarios, site deployment and shipping plugins. The solutions are pretty similar.

Site Deployment

The first situation is where you are deploying a site using GIT and Composer. If your live server has Composer installed — a rarity for some bizarre  reason in the WordPress managed hosting space — then this is easy. Use Composer to manage dependencies and gitignore the vendor directory and when you deploy use the –prefer-dist argument to tell composer to not checkout the whole GIT repo.

Laravel Forge, which is a server provisioning and deployment system of industry, has this line in its default deploy script:

composer install --no-interaction --no-dev --prefer-dist

This tells Composer to install with none of the packages that are required for development only, like your unit test framework, and to get the packaged distribution of the dependency, not the whole GIT repo. I have no idea what --no-interaction does, but let’s assume its good.

You probably want to add –optimize-autoloader to that if you’re not using Laravel, which runs that in one of its post install scripts.

Plugins

CalderaWP WapuuI make more plugins than I make sites. Most Caldera Forms add-ons use Composer to manage at least two dependencies. I’ve written a Grunt script that helps automate this process. It checks out all of the dependencies using composer update --prefer-dist and then copies everything to a sub directory, which it then zips and deletes.

This means that my plugin repos, have a directory, usually called releases, with a ZIP file I can upload to our site. I used to add an automated SVN deploy when I was working on plugins that need to go to WordPress.org. Now I just open that ZIP file and drag it into a new tag inside the SVN repo, opened with phpStorm and commit that.

What Else?

TL;DR Alot
Photo by: Jasper van der MeijThere are a few other challenges when using Composer. But I really do think they are outweighed  by the benefits. Composer is an essential part of the workflow for modern WordPress development.

Nor are these issues unique to Composer. I should probably write a follow up on using Bower Installer to solve a similar problem with Bower and NPM.

Composer is a great tool, and I hope you will try it, and when you do, this will have helped you learn how to make it work properly with GIT.

 

Lessons Learned Coding A Big, New WordPress Plugin

Over the last few months I’ve put a lot of time into writing Ingot — an automated A/B testing and conversion optimization plugin for WordPress. Because Josh, I did a lot of other things at the same time — but Ingot was my biggest project.

Ingot is probably the biggest plugins, in terms of lines of PHP code, that I wrote. I’ve worked on bigger plugins, but never as the primary developer. Pods and Caldera Forms are bigger, but my contributions code-wise to those are not huge.

For Ingot I wrote all of the PHP code. Roy Sivan helped me build the admin interface, which is an Angular app. He was also a valuable sounding board and bug catcher for the rest of the plugin.

I wanted to share some of the lessons I learned, as a developer, writing a big plugin. Writing this plugin from scratch allowed me to put to test a lot of my personal opinions on WordPress development. I’m going to follow this article with one specifically about coding a plugin around the WordPress REST API and another with some lessons I learned as an entrepreneur from the process.

ingot-logo

Separations of Concerns

Working with the WordPress REST API helps encourage separation of concerns because of the way defining routes breaks up the process of preparing, processing and responding to requests. In addition, knowing that some of your CRUD will happen via your REST API, but not means you either have to wrap your API callbacks around a standard set of CRUD classes, or you need to keep two ways of reading/ writing/ validating and sanitizing data in sync.

The latter of those two options is insane. I went for the first. Ingot has a CRUD class for each of the different data types — test groups, variants, sessions, click tracking, settings — each of which extends a base class. Having separate CRUD class keeps the validation, sanitization and DB writing separated from every place that CRUD is ever used, including the REST API routes, and objects that represent groups or tests.

This also led to having one class to handle read/writes and  establish a pattern for using CRUD, along with smaller extending classes to define what fields are needed. I liked working this way. Even though these classes are likely to be called multiple times, I used all static methods for them. Yes, there are objects for single groups, tests and sessions that are often needed, but CRUD is just a collection of functions and without any application for an iterator, having to instantiate multiple objects of these classes wouldn’t have provided any utility.

I think of these classes much like how WordPress core’s WPDB class, which might as well be all static methods since we always use one instance, relates to WP_Query. We use WPDB to inject post collections into specific WP_Query objects that we can then iterate over.

The way I worked wouldn’t have been doable without late static bindings. In non-static methods, $this refers to the current object. So if the class is extended, $this is the object of the extending class. The self keyword doesn’t work that way. self in the parent class refers to the parent class, not the subclass extending this.

On the long list of reasons why I didn’t hamstring myself with conventions of a language that is almost 8 years out of date (PHP 5.2) is late static bindings. Late static bindings allow for static inheritance. The keyword static functions like self, except it can refer to a subclass method or property if one exists.

One thing I’m really proud of in Ingot is that I stuck to very small classes. For example, I have a class that creates a conversion rates stats object. This is separate from the class that creates an object for stats for all of the variants in the group, which is a collection of the objects of my conversion rates stats class. This creates re-usable code — the conversion rate class is used for variant and group stats, easier testing, and avoids code reuse.

Small, reusable classes are not just neater and more testable, they make refactoring easier. I rewrote about half of Ingot in the week before release. Short story — CRUD was overcomplicated and the testing algorithm was going to require tons of traffic, which would be a problem for a big part of our target audience. That’s a different discussion, but my point for today is that small classes meant more saved code during that refactor since it was very easy to separate the parts that still had a job from those that didn’t.

This is a concern moving forward. I am considering whether it makes sense to break the plugin into smaller Composer packages that I can assemble into different, smaller, task specific versions. Doing so could also allow for implementing a CRUD system that uses the posts and postmeta table instead of custom tables.

Composer & Dependency Management

Photo by: Steven SpassovI used Composer for dependency management and providing a psr-4 autoload. There is a ton of blog posts out there on why I love Composer and dependency management in general. The PSR-4 autoloader forces a directory and class naming structure on the plugin that makes it highly organized. Between that logical organization and being meticulous about inline docs, I think the code is easy to follow. We will see as other developers get into it.

I did hit some stumbling blocks with dependency management. I used Composer’s file map for including PHP files that are not classes, which I found to be annoying. Classes are added automatically to the autoloader, since it is based on logic. File and class maps are static lists of files and adding to them requires a composer update, which I didn’t always alert Roy to, causing unneeded errors on his end. It also makes switching Git branches a pain.

I chose to use Bower for managing JavaScript and CSS dependencies. Bower is a pretty slick tool, but ZIP file for the first beta version after I started using Bower was 2 or 3 times the size of the previous version. This was because I was enqueuing the scripts from bower_componets.

My solution was to use bower-installer to copy all of the main files — IE the ones I needed — to a separate directory. This allowed me to exclude bower_components and all the extra stuff from the final zip.

I went on a bit of a quest to reduce the file size of the zip files I was creating for releases. Another big win was setting this command in my build script:

composer update --no-dev --optimize-autoloader --prefer-dist 

This pulls in the Composer dependencies without their Git repos, or unit tests and optimizes the autoloader. Even with just a few dependencies, the file savings were pretty nice — about 6GB. Git repos are big.

Since the plugin is in a public Git repository I don’t think removing all this extra stuff that most end users don’t need does anyone a disservice or reduces their rights to modify the software. If an end user is a developer and needs the whole package, they can get it on Github.

I actually used very minimal third-party dependencies. But my testing library, the one I switched to later on, started out as a third party dependency. The library I used was built to use Redis to store data. So, at the least I needed to add a way to store data using my CRUD system.

Photo by: Marta PawlikAt first I kept the testing library checked out from the original source — and that author merged my pull request to fix a bug I found. In order to facilitate this I kept my class to save data using my CRUD in Ingot instead of in the library.


As I found more places where my usage of that library wasn’t fitting well with the original design, I had to make more changes that didn’t make sense as pull requests. So, I started using my own fork and making changes directly there.

I will soon evaluate if my fork makes sense on its own, as a version of the original that stands on its own and is useful to have as a separate project or if it needs to be absorbed into Ingot fully. Either way, being willing to dive into a dependency, learn it, and modify was the difference between throwing it out and having to do another huge refactor and being able to ship the plugin on time(ish).

Iteration vs Throwing Shit Out

Photo by: Rick WaaldersI had a lot of fun with this plugin. Working on something that doesn’t have any users yet is really nice. Once a project is released backwards compatibility and stability are concerns. When you’re iterating on something pre-release, you get to break stuff and start over.

It’s funny how quickly I can fall into the “fix it, don’t break it” mode out of habit that comes with maintaining plugins with lots of active users or contributing to WordPress. I literally had to tell myself a few times “don’t work around that bad design decision, you wrote it yesterday.”

As I said before, I re-did the base A/B testing algorithm pretty late in the process. This led to re-doing a lot of the CRUD and re-working the REST API and a lot of other parts of the plugin.

The lean startup mindset dictates the idea of getting to a minimal viable product quickly and improving it from there. WordPress preaches the idea of continual iteration. I agree with these mindsets and think that they work together well.

That said, neither of them can be an excuse for putting out something bad. When I started on Ingot I create a minimal viable A/B testing algorithm assuming I’d get it right — statistically speaking later — once I had everything else working.

stained-glass-110788_1280This made sense to me, and once I had everything else working I sat down to write the code to do the math. I could have done it and I wrote a lot of it, but I realized that my approach was wrong. Not only that, I was adding it on top of some mistakes I made in the structure of my CRUD — separating price testing from content testing.

So, I spent “two days” throwing out half of the plugin and starting over. It was painful to throw out that much code — OK, I enjoyed it because Josh — but I’m glad that I corrected my mistakes before version 1.

There are somethings you can only do right, by doing them once in a way that is sub-optimal. Knowing when to throw out tons of code that works, has unit tests and documentation is hard. It’s not worth doing when it’s because you could have made the code cooler.

End-users don’t care about how fancy the code is, they care about results and they care if you can keep it working over time. Refactoring in order to meet your product design goals better, and to ensure your code will be more easily maintained over time is worth it.

Give It A Read

A yellow flower in out-stretched hands.I hope you learned something from this post. I’ve resisted the urge to put in big code examples, as I wanted to keep it abstract. That said, you should feel free to read the source code. I’m happy to discuss these decisions I made, or how you can integrate with Ingot. Leave a comment or tweet at me.

Tomorrow I’ll post my feelings on what the WordPress REST API means for plugin development moving forward. It’s obviously something I’ve thought a lot about and putting my own theories into practice was one of the most valuable parts of this whole experience.

How The WordPress REST API Changes WordPress Plugin Development

 

Extending The REST API Talk

My fall 2015 WordCamp talk is on extending the WordPress REST API. I love doing tweaky server-side PHP development, so I fell in love with the REST API, and even more with the extending it. I’m excited to be giving this talk a few times and hope to have video of it up soon.

You can see my slides, video from the talkm and a helpful list of links below.

By the way, did I mention I wrote a book on the REST API? Well I did, and it’s both awesome and free — thanks to the good people at Torque and WPEngine. You can down download it here.

In my talk I give an introduction to extending the REST API by modifying the default responses and creating your own endpoints. If you’re like me, and learn by reading code, I recommend checking out these two plugins I wrote:

  • SEO REST API Fields This plugin exposes SEO fields for WordPress SEO by Yoast in post endpoints, and allows for updating them along with the post data.
  • SearchWP API This plugin adds a custom endpoint for doing advanced queries, powered by SearchWP — an amazing WordPress search plugin — using the REST API.

I wrote a post a few weeks ago on the topic of extending the REST API, with more links to docs, and articles I wrote for Torque. Be sure to check that out.

 

Extending The WordPress REST API

Remember the first time you got annoyed WordPress didn’t do something, and then you realized with the right amount of Googling, experimentation and foul language, you could probably make it do that?

I don’t exactly, but some how it got me to where I am today, and I’m pretty happy about that :)

Hopefully, we will soon have a RESTful API in WordPress core. Since this is WordPress, the features of the REST API are sensible defaults, designed to work on tens of millions of sites. That means that there will be plenty of cases where the default routes do not fit the exact needs of a site, app, plugin, or theme.

Of course, since this is WordPress, the REST API is highly extensible. I’ve now written two articles on extending the REST API for Torque, and contributed to the docs on this subject.

I’d like to give you a brief overview of how to extend the default routes, and add your own, and show you some examples of plugins I’ve created to do  both. In addition I’ll link to the Torque articles and documentation to help you learn more.

But First

Version two of the REST API is on WordPress.org!

Version 2 of the REST API can now be installed as a plugin from WordPress.org. This makes testing easier. The two versions are separated so those relying on version 1 can continue to do so.

In the future the plugin will provide backwards compatibility for version 1 routes and endpoints, once version 2 has been merged into core. At this time, backwards-compatibility is not complete to version 1, and anyone relying on version 1 should continue to use the version 1 plugin.

The oAuth1 plugin from the REST API team will be available on WordPress.org soon.

Extending The Default Routes

add_filter( 'the_content', ...

WordPress ships with a really comprehensive set of URL mappings, that are all most sites need. But that doesn’t mean that an off the shelf theme, shows all the data you need. That’s why we modify template files, or hook into the_content to show custom fields and other non-standard data.

The REST API comes with a really useful set of default routes and endpoints. But those default endpoints are not always going to show the data you need, or give you the ability to update all the data that you consider part of the post/ term/ user / comment.

The REST API has a really helpful function called “register_api_field” to add the ability to read and/ or write new fields, from custom fields or any other source to an existing endpoint.

I covered using register_api_field, as part of my article for Torque on working with post meta data via the REST API. I actually turned the code examples in that article, showing how to read and write SEO title and description fields via the API into a plugin, which is in beta now, and we will be released at CalderaWP soon.

I wrote a few more examples of using register_api_field in the documentation site for the API. The version 2 docs are coming along nicely BTW. If you are looking for  away to contribute to this project, docs are a great, and needed way to help.

Rachel Backer, co-lead developer of the REST API project gave some examples of how this cool function works during her recent WPSessions presentation, which I strongly recommend watching.

 

Add Your Own Endpoints

$query = new WP_Query( …

The WordPress REST API is not just at the default API routes and endpoints, it’s infrastructure for creating APIs. That infrastructure is really well done. As someone who has rolled my own API on many occasions, I look forward to the day, when I’ll be able to take all of this API infrastructure for granted.

Custom endpoints are really useful for when you don’t actually want to query with a core query tool (WP_Query, WP_Users, etc.) but want to wrap some other function, or class. I’m particularly fond of the fact that I can now create classes for fetching and saving data, and then easily wrap an API endpoint around it.

On thing I love, about custom endpoints is that the API establishes a pattern of separating sanitization, validation, permissions checking, processing and responding into discrete methods in your class. Also, as this becomes the standard, hopefully we will see less misuse of admin-ajax in the front-end.

After writing about creating custom endpoints for the REST API in Torque, an article based on the CalderaWP API, I created an add-on for SearchWP, that allows for using that plugin’s awesome search powers via the REST API. After reading my article, I recommend reading documentation for adding endpoints. It explains how to follow the core API patterns and provides some good, generic example code.

Needs Help Figuring Out What To Do?

I know, it’s a lot

This can be a lot to digest. If you’re getting ready to jump into a project involving the REST API, you may not be sure if you should extend the existing endpoints or add your own. It’s a tough question, and the answer varies from project to project.

If you need help preparing for this type of project, I offer consult calls to sort through these types of questions and provides guidance moving forward. I also love doing custom development with the REST API, especially when I get to write custom endpoints.

Let me know how I can help :)

Access Control Headers For The WordPress REST API

Sending headers, including cross-origin (CORS) headers has changed a bit in version 2 of the WordPress REST API. Access control headers are sent by the function rest_send_cors_headers(), which is hooked to rest_pre_serve_request. You can easily change the headers by unhooking that function, and adding your own.

Below are some examples using access control headers, but really any type of header could be added here. That said, keep in mind that the class WP_REST_Response, which should be used for all responses, also gives you the ability to add headers. Any headers unique to a request should be set there.

/**
 * Use * for origin
 */
add_action( 'rest_api_init', function() {
    
	remove_filter( 'rest_pre_serve_request', 'rest_send_cors_headers' );
	add_filter( 'rest_pre_serve_request', function( $value ) {
		header( 'Access-Control-Allow-Origin: *' );
		header( 'Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE' );
		header( 'Access-Control-Allow-Credentials: true' );

		return $value;
		
	});
}, 15 );


/**
 * Only allow GET requests
 */
add_action( 'rest_api_init', function() {
    
	remove_filter( 'rest_pre_serve_request', 'rest_send_cors_headers' );
	add_filter( 'rest_pre_serve_request', function( $value ) {
		$origin = get_http_origin();
		if ( $origin ) {
			header( 'Access-Control-Allow-Origin: ' . esc_url_raw( $origin ) );
		}
		header( 'Access-Control-Allow-Origin: ' . esc_url_raw( site_url() ) );
		header( 'Access-Control-Allow-Methods: GET' );

		return $value;
		
	});
}, 15 );


/**
 * Only allow same origin
 */
add_action( 'rest_api_init', function() {

	remove_filter( 'rest_pre_serve_request', 'rest_send_cors_headers' );
	add_filter( 'rest_pre_serve_request', function( $value ) {
		header( 'Access-Control-Allow-Origin: ' . esc_url_raw( site_url() ) );
		header( 'Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE' );
		header( 'Access-Control-Allow-Credentials: true' );

		return $value;
		
	});
}, 15 );


/**
 * Only from certain origins
 */
add_action( 'rest_api_init', function() {

	remove_filter( 'rest_pre_serve_request', 'rest_send_cors_headers' );
	add_filter( 'rest_pre_serve_request', function( $value ) {

		$origin = get_http_origin();
		if ( $origin && in_array( $origin, array(
				//define some origins!
			) ) ) {
			header( 'Access-Control-Allow-Origin: ' . esc_url_raw( $origin ) );
			header( 'Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE' );
			header( 'Access-Control-Allow-Credentials: true' );
		}

		return $value;
		
	});
}, 15 );


I have a plugin for setting CORS for GET requests and a plugin for setting CORS for ALL requests on Github.