It’s that time of year again. I’ve updated this theme, which runs off my open theme + a few minor style tweaks.
What’s new in v2.0?
It’s all completely under the hood. So you’ll see nothing different here… But I’ll know.
First, since I build the theme, react-router hit version 4 and changed everything. There are a whole lot of changes in this theme due to that. One huge benefit to this update is that now it is much easier to integrate state into your redux flow. You can see how to implement react router 4 in the index.js here.
Also, since building the original I started using ReactJS at work, and learned a lot about how things flow, and how to keep things clean. So many of the changes have to do with duplicate code, and cleaning up the flow of data. There’s still much that can be done, but it’s a nice step in the right direction.
Bootstrap finally went from alpha to beta, so I’ve implemented that, and a few minor tweaks to make everything work. I almost lost the header for a minute…
Another piece I started implementing is a proper php fallback. When I first build the theme I thought it would be cool for it not to rely on php at all. But let’s be real, sometimes there are browsers that hiccup, and people don’t use the tools they should, so I thought it would be prudent to make the simplest functioning theme in php to fall back to. It’s not done, so for now they’ll see a list of titles…
Go check it out and I’d love to hear your thoughts.
As always, questions? comments? shoot me a line!
Setting up a Vagrant box can be painstaking.
Here is the process:
- Install a basic box.
- SSH into said box.
- Run a command.
- If it works, add the command to a provision file.
- Destroy your box.
- Run the box again and see if the command works via a provisioning file too.
- Whether it works, or doesn’t work, back to step 2 and try a new command or try the same command another way — depending of if it worked or not.
This is a really good way to get to know what your system’s administrator does every day. It includes a lot of reading manuals and playing with configurations.
If you want to understand your server better, there is no better (and safer) way. An added benefit is that doing this will also give you confidence in your development skills, as you’ll understand more of what goes on beneath the surface.
Warning: This process will take you days. At least at first.
VVV is great, if you don’t want to think about what you’re running. Its imprint as a local environment is bit heavy though.
Since I’m partially responsible for running the server at work (together with our security professional), and I run the server that this site (and a few others) is hosted on, I do like to think about my server. I think about it a lot.
Please don’t consider contents from this post as best pratice for running a production server. There’s a whole lot more security and settings involved.
I just updated my local development vagrant box. I thought I’d share what I learned upgrading it so that you don’t have to go through steps 2-7 above 80 gazillion times.
- Ubuntu 16.04 (Xenial)
- Python 3
- Nginx 1.13
- PHP 7.1
- Percona 5.7
How do I get started with Vagrant?
Vagrant automates setting up a server. What this means is that you can clone a git repository with the settings to run a specific environment, type
vagrant up and you don’t have to know any more than whether you trust the person who designed that environment.
It’s also free, unless you need to use it with VMware. Which makes it very popular among use developers who love free software.
To get started with Vagrant all you need to do is download the latest version of Vagrant, and VirtualBox. Make a folder somewhere and go to it in your terminal. Then type
vagrant init and then
How do I use your repo, I don’t care how it works?
- Download and install Vagrant and Virtual box.
- Clone the github repo
vagrant upfrom the directory.
192.168.33.10 play.lclto your hosts file. (See “What is a hosts file?” below for details.)
- Go to http://play.lcl in your browser.
Why should I run Ubuntu Xenial on my Vagrant box?
Ubuntu is one of the easier, and stable, Linux distributions to maintain. The apt package manager is simple to use and has a great community contributing to its upkeep. In addition, it tends to offering later releases of tools than most other distributions.
One alternative, CentOS, uses yum as their package manager, which is also pretty good, but doesn’t offer as many recent releases of packages as apt does. I’ve used it a lot. One great benefit is that CentOS has an Enterprise edition (Redhat). If you are required by your company to use Enterprise software, so that you can blame someone if something goes wrong, CentOS/Redhat is not a bad way to go.
I’ve had to use SUSE as well, I had to for a while. Pity me.
As of the last time I used it, there was no meaningful package manager. That means that if you want something that’s not already packaged with SUSE you had to hope that someone (who you had to trust) had compiled a version that would work… Or you had to compile it yourself. Not safe or fun.
So let’s start with the box itself. Hashicorp, the creator of Vagrant, provides a basic Ubuntu box for most major releases. Other people release boxes as well, but I like mine clean so that I know what’s on the box when I begin with it.
Your basic install will go like this:
vagrant init ubuntu/xenial64.
This will create your most basic configuration file. I recommend reading that file. It will give you an idea of what you can do with your configurations. If you type
vagrant up you’ll have Ubuntu 16.04 running.
Ubuntu alone, though, won’t help you with your development much. You’ll need git to get other tools, you’ll need a server to serve files to your browser, some compiling language to run your code and serve to your file server, a database… But a basic OS is a good start.
What is a hosts file? How to I run my local site from a URL and not an IP address?
When your browser tries to load a domain it goes out to a DNS (Domain Name Server) which is a database of domains that point to IP addresses, then your browser goes to that ip address to load the content from the server that hosts the site you are looking for.
Before it goes out to the DNS, your broswer checks a file on your computer called the hosts file. In your hosts file you can tell it any IP address and a domain, and your browser will go to that IP address when you type the domain into your browser. So if you want to use a domain that doesn’t exist you can edit your hosts file and add the domain you want.
You can also override existing domains this way. This can be used nefariously, as I’m sure you can imagine. But it can also be helpful. I’ve used this several times when I wanted to set up a new server. I pointed my local hosts file to the new server’s IP address and set everything up there. Once it was all good, I told my domain hosting provider the new location of my site. BOOM. That’s it.
So if you want to develop locally on google.com you can point google.com in your hosts file to your virtual machine’s local IP address. But it will get confusing if you need to look something up, you won’t be able to access the real google.com until you change it back.
Note: If you play around with this some browsers (ahem Chrome) cache the ip addresses and even if you change it back in your hosts file you need to flush various caches of your browser to access the proper servers again.
I personally like to use something like play.lcl. I’d recommend to use a TLD (top level domain, i.e. .com/.net) that doesn’t exist so you never try to reach a site that you’ve overridden the domain locally.
In order for your hosts file to work, though, you need to point the local domain to an IP address. You can start up your vagrant server, SSH in, run
ifconfig and get your IP address that way. But if you reload your local server that ip address might change, and will from time to time.
Enter the static ip:
config.vm.network "private_network", ip: "192.168.42.10"
If you add this line to your Vagrantfile, you’re telling Vagrant to always set up the server to use that IP address. You can choose anything in the private address spaces. What this will do is make sure your box runs of that same IP address each time. So when you reload your box, or shut it down for a week, it will be the same IP address when you
vagrant up again.
Note: If you are running multiple boxes simultaneously, make sure you use a different IP address, or shut down the other boxes.
Now edit your hosts file and add the line:
I like to use Gas Mask to manage my hosts file on my mac.
Once your server is up and running you’ll be able to access it in your browser from the URL http://play.lcl. Sometimes the first time you type it in you need to add the http:// otherwise your browser will search for the domain in your default browser instead of looking it up in the hosts file.
How do I not lose my code files when I destroy my Vagrant box?
One of the benefits of Vagrant is the built-in functionality for synchronizing folders. Back before I was using Vagrant I had to jump through hoops to back up my files on my local environment, now it’s baked-in.
In your Vagrant file add
config.vm.synced_folder "./html", "/var/www/html", create: true
This will synchronize the files in the html on your computer to /var/www/html. Which is usually where servers run their code from. If the folder doesn’t exist, it will create it for you.
How do I customize the amount of memory my vagrant box has?
If you’re running a local server with programs that need more than a default amount of memory, or less for that matter, you can add the following to your Vagrantfile…
config.vm.provider "virtualbox" do |vb| vb.memory = "1024" end
This will set aside 1gb of your computer’s memory for your box.
How do I tell Vagrant to run install scripts when it starts up?
There are two ways to do this:
The first is inline.
config.vm.provision "shell", inline: <<-SHELL # run some code here like... apt-get update SHELL
The other way is in separate files.
config.vm.provision :shell, path: "assets/clean-update.sh"
What this does is let you keep all your code neat and easy to find. You won’t have to sort through files that are hundreds of lines long to reconfigure one little thing.
Why does my Vagrant box break when I upgrade everything?
I like to keep things up-to-date. It’s a good way to protect yourself from security issues, or use the latest and greatest features. It’s also a good way to break your code or server. But if you’re running a local server, then there’s no problem there. Test it locally, if it works, apply on production. The beauty of a local server.
Here’s how you play:
- Copy the entire vagrant folder somewhere else.
- Halt all other boxes.
- Run vagrant up in the new copy.
apt-get clean all apt-get update apt-get -y upgrade --with-new-pkgs apt-get -y dist-upgrade apt-get -y autoremove
This updates and cleans up pretty much everything. Some of these commands are redundant, I have them in there so I can comment one or the other out and provision.
The problem with many base Vagrant base boxes is if you run this, you’re likely to destroy some local configuration and your box won’t continue to run as it had been. That’s why I like using the basic boxes as my base…
vagrant init ubuntu/xenial64. Other people/companies provide basic preconfigured boxes, but if you want to play around with Linux configurations you will want to start with something clean.
Note: If you’ve cloned this repo and are using it locally to develop your code you don’t want to run
vagrant reload --provision without first testing your code elsewhere.
How do I install the latest version of Git on Ubuntu Xenial?
If you’re going to install other packages on your box you’re going to want Git to get started. By default Ubuntu doesn’t come with the latest version of Git. It’s pretty recent, but not the latest. If you want the latest you can use the ppa for git-core.
apt-add-repository ppa:git-core/ppa apt-get update apt-get install -y git
You’ll notice no
sudo that’s because vagrant provision files by default will run as a sudoer. If you don’t want it to, like if you’re installing node packages, you’ll need to add
privileged:false to the end of the line in your Vagrantfile, like so:
config.vm.provision :shell, path: "assets/node.sh", privileged: false
Why isn’t Python 3 the default Python for Ubuntu?
Python 3 is a pretty awesome update over Python 2. There are lot of new things under the hood, but a lot of other features athat are not100% backwards compatible. Since so many tools have been built in python 2, most default installations are python 2. Nonetheless, the transition is on the roadmap for future releases of Ubuntu. If you want it now, you can easily run python 3 on your sever.
apt-get install -y python3-software-properties python3-pip python3-dev
As in life, you really only need to know what you’re looking for in order to find the answer. There are versions of most of the tools for python with a 3 appended to the install command.
How do I install the latest version of Nginx on Ubuntu Xenial?
First, why nginx?
Nginx is ridiculously fast at serving static files. It was built from the ground up to do so, and at its inception was basically trying to solve the issues that apache had.
If you do go with nginx, you’ll need to run something for your dynamic content — like PHP. This isn’t a big deal, you can run php-fpm and you’re good to go. PHP traditionally is a module running on top of Apache. PHP-fpm runs along side the server instead of on top of it. The benefit of doing this is that php it will make a smaller imprint on your resources.
Ok, how do I install it?
Like git, the latest nginx does not come with apt out of the box. But Chris Lea has compiled it for you all to use.
add-apt-repository -y ppa:chris-lea/nginx-devel apt-get update apt-get install -y nginx
How do I install a self-signed cert on Vagrant? How do I get ssl/https on Vagrant?
With Google giving preference to ssl secured sites it’s a good idea to be able to develop and test your code in similar circumstances. You can automatically create a self-signed ssl certificate like so:
mkdir -p /etc/pki/ssl cd /etc/pki/ssl openssl genrsa -out play.lcl.key 2048 openssl req -new -x509 -key play.lcl.key -out play.lcl.cert -days 3650 -subj /CN=play.lcl
Then you can add the following to your nginx site .conf file:
listen 443 ssl; ssl_certificate /etc/pki/ssl/play.lcl.cert; ssl_certificate_key /etc/pki/ssl/play.lcl.key;
Just keep in mind, your browser is smarter than that, you’ll have to disable and affirm your kitchen sink and first-born child in the settings in order for it to load your local site over ssl. This is fine, because, do you really want insecure certs easily circumvented? Think of the non-technical people in your life…
How do I install php-fpm on my Vagrant box?
Now that you have nginx running you can’t install the apache module for PHP and expect it to run. Ondřej Surý provides a ppa for php-fpm’s latest release.
add-apt-repository -y ppa:ondrej/php apt-get update apt-get install -y php7.1 php7.1-bcmath php7.1-cli php7.1-common php7.1-curl php7.1-dev php7.1-fpm php7.1-gd php7.1-json php7.1-mbstring php7.1-mcrypt php7.1-mysql php7.1-tidy php7.1-xml php7.1-xmlrpc php7.1-zip
This line above will give you everything under the sun along with php, as well as a kitchen sink. Which is fine for a development server. When it comes to a production server it’s best to install the minimum and add only what you need. Otherwise you’ll have a lot to keep an eye on when you audit your sever and code for security issues.
What is Percona and why would I use it instead of MySQL?
Percona Server for MySQL® is a free, fully compatible, enhanced, open source drop-in replacement for MySQL that provides superior performance, scalability and instrumentation.
I met some of the good people who work there. Basically the back story is thus. A number of developers working on building MySQL were frustrated with the performance of MySQL and frustrated that the company was not implementing their ideas. So they forked it and improved it.
If you were to benchmark it you can confirm that it truly is superior.
How do I install Percona on a Vagrant box?
This is the tricky part. Percona has some configurations that you need to enter as you’re installing it. But you don’t want to have to do that if you’re running a vagrant box. I would vehemently recommend against most of the practices you need to automate these installations when setting up a production server. But for the convenience of a local development server, here you go.
cd ~/ wget https://repo.percona.com/apt/percona-release_0.1-4.$(lsb_release -sc)_all.deb dpkg -i percona-release_0.1-4.$(lsb_release -sc)_all.deb apt-get -y update echo "percona-server-server-5.7 mysql-server/root_password password root" | debconf-set-selections echo "percona-server-server-5.7 mysql-server/root_password_again password root" | debconf-set-selections DEBIAN_FRONTEND=noninteractive apt-get -y install percona-server-server-5.7
This will download the package to your home folder, add it to apt then update apt. Next you’re setting the response to the configuration. Finally, you’re installing the Percona server with the noninteractive flag.
Note: This one took a long while to figure out, so thank me.
If you follow the installation script while it’s happening you’ll notice that there are commands you need to run to get the full benefits of Percona. Here’s how to run them in your provisioning script.
# restart after reconfig service mysql restart mysql -e "CREATE FUNCTION fnv1a_64 RETURNS INTEGER SONAME 'libfnv1a_udf.so';" mysql -e "CREATE FUNCTION fnv_64 RETURNS INTEGER SONAME 'libfnv_udf.so';" mysql -e "CREATE FUNCTION murmur_hash RETURNS INTEGER SONAME 'libmurmur_udf.so';" sudo mysql -D mysql -e"update user set plugin='mysql_native_password';" sudo mysql -D mysql -e"flush privileges;"
How do I install NVM on my Vagrant box?
This is another one that took some time to figure out.
What is NVM?
NVM stands for Node Version Manager. It’s a really simple tool for installing and jumping in between different versions of node. If you want to use the latest version of node you only type
nvm install node then
nvm use node and boom. You’re using the latest node. You can also specify a version. This was more helpful when Node had been forked and you wanted to test IOJS. Node has matured somewhat since then, and there’s less of a need. But it’s still helpful for building packages or troubleshooting.
cd ~/ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash source ~/.nvm/nvm.sh echo "source ~/.nvm/nvm.sh" >> ~/.bashrc nvm install node nvm use node
This will run the nvm install script, then it loads it into your bash profile so that you can use it immediately in your script.
When installing node packages you should make sure to install them using the Unix user that you’ll be developing with. So when I run this file I run it set privileged: false, as I explained above.
How do I automatically install WordPress on my Vagrant box?
You have web server (nginx) a PHP compiler (php-fpm) and a database (percona) running. You’re missing WordPress. Enter wp-cli.
wp-cli is a command-line interface for maintaining WordPress. With it, you can install and update WordPress core, plugins, and themes.
Let’s start my installing wp-cli…
cd ~/ curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar chmod +x wp-cli.phar sudo mv wp-cli.phar /usr/local/bin/wp wp --info
This will install wp-cli on your box. Again, so that you can use it with your vagrant user run this in a non-privileged provision.
Next install WordPress:
cd /var/www/html wp core download wp core config --dbname=play_lcl --dbuser=root --dbpass= --dbhost=localhost wp db create play_lcl wp core install --url=play.lcl --title=Playground --admin_user=admin --admin_password=admin [email protected] wp theme update --all wp plugin update --all
This downloads the core to your html folder, yes, the one we synchronised before. It then creates the configuration file. Next it installs WordPress with the user:
admin and password:
admin. Finally, it updates the plugins and themes.
You no longer have to log into your dashboard and click update on all your plugins. Now one simple command does the trick.
If you’ve stuck around till here, thanks! Tweet: “Ooogaah Boogah” @jackreichert to let me know and show your appreciation…
Well that was a long brain dump. I update this project from time to time. I probably won’t go back to this blog post and update it. But I will push my changes. So you can star the repo for future reference.
If you have ideas on how to make this better, please feel free to comment below, or submit your thoughts on my contact page or even open an issue in the repo.
As this is going live I am currently giving a talk at @WPNYC the WordPress New York Meetup group.
There are two slides I skimmed over due to lack of time, but they are an essential part of the talk. In order to fulfill my promise to provide the complete story I am publishing this post with the full story.
Warning, this blogpost is a bit of a braindump. It is intended as notes to use to explore further. If you need something clarified, don’t heistate to comment.
The first slide is titled:
Tools of the Trade
With the following content:
- Separate development environment
- console.log() / error_log() / var_dump($var); die();
- debug_backtrace() / Xdebug
- Inspect Element / Developer Tools
- A good IDE
- Unit Testing
Let’s dig in…
Separate Development Environment
Never go commando, period. There are always exceptions to the rule — when you cannot reproduce a bug on your development server while it’s glaring at you from production — but you should avoid coding live on production at all costs. Sooner or later you’ll break something and your site will be down, and it was perfectly preventable.
This is as important as not ever modifying core WordPress files.
There are many ways you can implement a development server. Keep in mind that the closer your development environment is to production in how it functions, the fewer bugs you’ll have due to discrepancies in implementation of your code.
- XAMPP, MAMP and WAMP are all easy to use out of the box server solutions. I started out with them myself.
- Vagrant is a great way you can channel your inner sysadmin. But you don’t need to be one to use Vagrant. The good people at 10up support VVV. Or you can use the vagrant box one I built and use.
- Get another account on the server you are hosting your live site on. It’ll be worth the money, just make sure it’s not accesssible from the “outside.” Member’s only plugins can help with that. Or use the htaccess or nginx.conf files to limit access by ip address.
console.log() / error_log() / <pre>var_dump($var); die();
THE key to effective debugging is to know what you’re dealing with. These tools help you peek under the hood, test your assumptions, and understand what’s happening.
- error_log is similar to console, but server-side. Find out where your error logs are written to on your host. A server isn’t worth it’s salt if it doesn’t provide that. If you enjoy console.log check out console_log().
- While the error_log is cleaner, it limits its output. I find I like to see things in the browser, sometimes. I use this pattern, a lot, when debugging.
echo '<pre>'; var_dump($var); die();
It will “dump” the variable in a preformatted html tag, then die().
debug_backtrace() / Xdebug
Xdebug provides a whole suite of extended debugging methods. You don’t need to start here, but if you’re looking to up your game, here’s where to go.
Inspect Element / Developer Tools
Volumes of ink has been used talking about devtools, so I won’t go in depth here.
Firebug changed our lives. Read up on it, use it. Personally, I enjoy designing in it too. It’s not just for debugging.
I used devtoops to build this mockup to nag @Dropbox to request a feature.
— (((Jack Reichert))) (@JackReichert) January 7, 2017
A good IDE
The reason why this is essential is that it does a lot in the background to ensure good code.
- It can autoformat, which means you’ll reduce your syntactical bugs.
- Deep link to method sources, so you can more easily see what’s happening under the hood.
- Code completion will help you make sure you’re using the right method, and give you a reason to should “DAMN YOU AUTOCORRECT” every so often.
If you’re expected to support a specific device, you better test in it. Unfortunatly we can’t all afford every device under the sun, but there are a lot of tools out there to help us with that.
- Modern.ie provides virtual machines for testing different versions of Internet Exploreer.
- Use a mobile emulator sometimes making your screen narrower won’t cut it.
This is the single most important thing you can do to prevent bugs. It’s hard to get started. It’s overwhelming. But as the proverb says: the best time to plant a tree is 20 years ago, the second best time is now.
Protip: Think about testing BEFORE you write your code… Look up TDD.
The second slide is titled:
WordPress Specific Debugging Tools
With the following content:
- define(‘WP_DEBUG’, true);
- Debug Bar plugin
- All the Debug bar addons!!!
- Style Guides
There are a number of constants you can define in your wp-config.php file that can help your debugging in WordPress.
Debug Bar plugin
The Debug Bar is the equivalent to the devtools, but for WordPress. If you enable it you’ll get a window into how WordPress runs that you can’t get easily otherwise.
All the Debug Bar addons!!!
Expanding on the previous tool. There are a ton of plugins that hook into the Debug Bar and extend it.
This isn’t necessarily a WordPress specific tip, but if you’re using PHPStorm it comes with an auto formatting preset of WordPress’ code style.
In any case, it doesn’t matter how you style your code (tabs vs. spaces) but only that you are consistent. If you are consistent with your coding style you’ll prevent a whole lot of bugs. You’ll prevent a whole lot more if you’re working with other people and you make sure you’re all styling your code the same way.
Our brains evolved to see patterns, if your code styling isn’t consistent, you’ll miss details. You’ll have bugs.
I hope this was helpful. There’s a lot I didn’t cover so as to not overwhelm. What’s really most important, which I covered in my talk is the following:
Make it work, then make it work well.
If you do this, your code will always be improving.
I think it’s just about done, so I decided to go ‘live’ with it.
You’re looking at it now. What do you think?
I’ll probably tweak it over the next weeks, months. But I’m itching to give it a test drive. For now it’s good enough for government work… which means a lot less than it did just a few months ago.
I’lll also write more about the process, and how it works asap.
Find a bug? Let me know.
In their discussion they Brian mentioned the Drafts with Friends plugin and how he’d like to see something like Google Docs collaboration, editing.
That got me thinking about what the MVP, minimum viable product, for that would look like… and I came up with the Request Post Feedback plugin.
Here’s how it works:
Under the content editor there is a new meta box. At the top of the box you can enter an email to generate a new feedback link. This is how Posts With Friends already works.
At the bottom of the meta box you can manage the different links that you already generated and see if someone has already given feedback.
When you send a link to someone they aren’t taken to the admin; rather, they are taken to the front-end of your site. Where the post would normally be, there is an embedded editor with the content of your post ready for their perusal.
When they submit their feedback it is saved as a revision post_type of your post.
What that means is that you can leverage the revisions browser comparison tool already built into WordPress and see what they suggested.
If you like the concept try it out. It’s not yet live on the WordPress plugin repository, because I haven’t decided if I’ll maintain it yet. But I welcome you to download it from the project repo and try it out. Please note: while I made sure that it was solidly built, it’s still an MVP/Proof of concept.
As always please share your comments below.
To being, check out the project here.
This is a work in progress, but I got enough done this weekend that I’d like to share.
I wanted to work on a project using ReactJS and Redux. I’ve heard a lot about it, and wanted to explore it on my own. I do that with every technology before I bring it to the office. Since WordPress incorporated the WP REST API in the core for version 4.7 I though that that might be a great opportunity to explore both the API using ReactJS+Redux.
There were a number of interesting challenges I faced building this. The idea was to make a theme that would work 100% like any other WordPress theme; that could be installed and work normally.
As it currently stands there are some missing features, which I’ll get to later. But this is past a proof-of-concept and well along the path to be fully operational.
I will explain more about how it all fits together in a future post, maybe when I load it onto this site. In this post I just wanted to muse about the process so far, and invite others to join in the project or share their ideas and implementations.
Endpoints: Handling Pretty Permalinks
The first challenge was to figure out how to handle “Pretty Permalinks.” You know what they are. Back in the early days of CMSs all URLs ran off of GET variables (http://blog.example.com?p=23). But because Google gave better SEO juice to readable URLs we all started getting urls that were readable. This was incorporated into WordPress as well.
The problem with implementing this in a single-page JS app is that the default path for posts is
/year/month/name-of-post/. That can make routing complicated. Not only that, but you can change the permalink format too. So in order for this theme to work, I’d have to handle that.
My solution was to have a catchall route and build a custom endpoint for Pretty Permalinks that would be powered by the url_to_postid() method. This ended up working pretty well and is what powers both single pages and posts.
Another challenge was how to handle menus. They’re dynamic, and not included in the current API. To solve this I borrowed the main class from the WP API Menus plugin. (I love GPL, don’t you?) It was written by Fulvio Notarstefano, and was beautifully implemented.
I contemplated having the menu data loaded as js variables on page load, since they don’t change. But I wanted the challenge of figuring out how to implement multiple versions of the same element with ReactJS+Redux, so they got their own endpoint.
Endpoints: Featured Images
I also modified the main post endpoint to include featured images so that I wouldn’t have to do a separate call for each image on archive pages.
Another challenge, in general, was handling the different routes for different actions. It’s not all that complicated once you get the hang of it. But working in single page apps can get interesting, and if you’re not careful you can lose the benefits of using frameworks like Redux.
All in all the WP REST API is quite robust and is now polished. If you check out my redux actions you can see that I’m using the same endpoint for the main index archive, single posts and search. Which is really nice. I’ll be expanding this file for the taxonomies as well. Apparently all you need is to add a filter GET variable.
What’s still missing from the project?
There’s still a lot to do. First and foremost, there is currently only minimal styling.
There are a whole lot of things that are needed to make it a theme the might be accepted into the theme repo. First of all, I haven’t done anything with taxonomies yet.
I’d also like to add widgets. That is another interesting problem which I’ll probably solve the same way I did pretty permalinks — add a new endpoint just for them. I’ll have to render them completely on the server, then pass them down via the API. It’s not pretty, but it should work.
I’ll also want to clean up the hooks that run before the page loads. Since the entire theme is running off the API, directly from the index.php, it won’t need a lot of the server-side processing, as that is done already in the API.
The customizer isn’t playing well with the menus, I’ll have to figure that out.
I’m sure there’s a whole bunch more that needs to be done too. I’ll write about what I discover in the summary post once (if) this theme goes live.
It’s a fun project and I’ll look forward to playing more with ReactJS and Redux. The first thing I noticed was how snappy it was. It also forces you to think about the different components in a very healthy way. When designing components, each one should be independent. You should be able to drop any one in any other project (for the most part) and use it with minimal wiring up. That’s good coding practices.
If you find this project interesting please feel free to share with me your ideas for it.
Get a Mac! Kidding. (I actually think Microsoft has been more innovative lately.)
Run the flag
--no-bin-links when you install anything with npm and it will fix your issue.
I have a dev Vagrant that I share with my team. I tend to mock things up when I’m playing around at home in the evenings. I work on a Mac at home. So when I confidently came into work with the plan to set up a box for my team to work on, I lost a bunch of time trying to figure out why the npm development tools I wanted, would not install.
According to the npm documentation:
--no-bin-linksargument will prevent npm from creating symlinks for any binaries the package might contain.
Why? I found this discussion on the Vagrant github:
…there is a fundamental problem with using Vagrant + VMWare Workstation + Windows + Linux VMs…
It seems that VMWare on Windows simply does not support the ability to create a Linux symlink in a shared folder.
Another option is to set bin-links to false in your global npm configuration:
npm config set bin-links false
This will mean that you won’t have to type in the flag
--no-bin-links each time, which might be a good solution if you are trying to build development tools to make your team’s lives easier.
I recently dissected an Object Oriented WordPress plugin boilerplate. This exploration was part of a project I am undertaking to explore best practices for implementing Object Oriented principles in WordPress development.
When it comes to implementing coding principles, I’m generally not a purist — I aim to be utilitarian. One of the dictums I drum into my team is: “Make it work, then make it work well.” Do not take that to mean I’m sloppy, the second half of that statement holds as much weight as the first.
In the spirit of “make it work well”, I decided to refactor my Assets Manager plugin for this exploration, as I have not updated it in a while.
My goal here was not to create a pure Object Oriented plugin implementing all the glorious principles. There is a lot more I can do, and I will discuss some of those ideas as I explain what I did. Mainly, in this refactor, I wanted to accomplish the following:
- Implement the Single Responsibility Principle.
- Decouple the various components of the plugin from each other.
- Lay the groundwork for further implementation of more principles.
Single Responsibility Principle
Of of the banes of every developer is cutting through spaghetti code. I’ve discovered — from refactoring multitudes of lines of code — that the simplest, most effective way to reduce and prevent spaghetti is by applying this principle. Like spaghetti, your code cannot get tangled if it’s too short to tangle up.
Decouple the various components
While recompilation isn’t an issue with PHP/WordPress, there are still benefits to decoupling. First, reusability: if your components work independent of each other you can stash your pieces away for another project. You also don’t have to repeat your code if you need the same functionality elsewhere. Don’t Repeat Yourself!!!
But perhaps, more important than reusability is stability. The more interdependent components are in your project, the more fragile your project is overall. If you change one thing, the more other components depend on that piece, the more chance you have that you are breaking one of those other components.
This is the whole reason for the Open/Closed Principle as well as the Interface Segregation Principle. Aside from SOLID, though, this is also the reason why WordPress is riddled through and through with hooks. WordPress hooks allow for developers to change the functionality of the core, or other people’s plugins, without having to change the core, or foreign plugin, code.
If you look at the previous version you’ll see that the extent of Object Oriented implementation is an encapsulation of the code, and that’s about it.
This isn’t a bad practice per-se. If you are going to keep to best practices of compatibility standards with WordPress, you cannot use php namespaces in your plugins. Namespaces were introduced in PHP 5.3 and, as of writing this, WordPress still supports as far back as PHP 5.2.4.
A first step you can take when implementing Objects in your WordPress plugins is to wrap your code in a class. If you do this, you do not have to worry about the names of your functions conflicting with the names of other functions in other plugins. This approach is called the “God Class,” as it creates one class that does it all. It’s not all that sophisticated, nor is it really Object Oriented either.
On this topic, once you start adding classes to your plugins, there is a fascinating and thorough breakdown of the different ways to instantiate a WordPress plugin as a class on the WordPress Stack Exchange community.
Following is a breakdown of the files in the new-and-improved plugin:
This should be renamed to match the directory (assets-manager), but I’m not sure whether the plugin upgrade process will work if I do this. Because this file is not named as the plugin directory, it makes generating test suites more complicated, but it’s also not a big deal.
The main job of this class is to instantiate all the other pieces of the plugin; I may implement an autoloader here at some point. While this class is dependent on ALL the other classes, since the only thing it does is instantiate all the other classes, it still is a fairly stable class. It doesn’t care about the intricacies of the other classes it uses. As long as the function names stay the same, you will only have to change this class if you need to add another component.
The other minor job of this class is to ensure that the rewrite rules are flushed when the post type is being created. Yes, this class is supposed to do one thing, but other, more pure ways of doing this would be convoluted — creating then deleting options in the database. I thought that that was silly to do simply to keep with a guideline, so I opted for this small infraction.
When classes do one thing, they tend to be boring, and that’s a good thing.
I have an empty constructor here because the logical alternative would be to put into it the hooks call. That would make tests more complicated, so I didn’t do that.
I tried to include in here all the specific logic about how each individual asset works: the metadata, when are users allowed to access an asset, the asset link, etc. I did this to pull it away from the god class. The next step will be to pull out the specific restrictions as components onto themselves.
Currently, they all hook into
pre_asset_serve which is a hook I put into the class that serves the asset. Each restriction should independently hook into the asset class.
Additionally, the UI is still intertwined with Admin.php, so if you were to add features to the asset, you would need to change that, as well as the JS file. I think this is a step in the right direction, perhaps next iteration will include this decoupling.
This does exactly what it says, nothing else. It hooks into WordPress before headers are sent, if the request is an Asset, it serves that request.
This was built with the Open closed principle in mind, open for extension, closed for modification. One of the most powerful features of WordPress are the hooks; which, are the embodiment of the Open closed principle.
Every WordPress developer learns at one point or another early in their career that you do not change the core, or anything that may be updated for that matter.
How is this learned?
Well, they make a change, to the core, or a plugin, or theme. Then, at some point in the future they forget that they had made that change and they update whatever it is they made the change to.
And everything breaks.
Well, maybe not everything; but whatever they were trying to accomplish with their modification is now lost.
Hooks are peppered throughout the core, well developed themes, and plugins. They allow other developers to hook into the code and tell it to do something without changing the code. This way when an update comes out, they can update without losing those changes.
Serve_Attachment.php has the hook
do_action( 'pre_asset_serve', $this->attachment_id ); before the asset is served. I eat my own dog food here and hook into that action from Check_Asset_Restrictions.php to see if that asset should actually be served.
This is the other side of my implementation of the Open Closed principle, discussed in the previous file.
This class hooks into
pre_asset_serve and runs all the checks it needs to. This class needs to have a certain amount of knowledge about how Asset.php works, so it’s not ideal. This is another example of how it’s a work in progress.
The fun thing about this is it runs entirely on hooks. It hooks into
pre_asset_serve and it has a filter itself through which others can change the
This class is responsible for the admin display of the assets on the post type page.
As I wrote above. Ideally, each feature of the asset — expires, require login etc. –should be a separate component hooking in here, and where the file is served. Perhaps I’ll do that in the next iteration. Doing that would coincide better with the Interface segregation principle.
As-is, it think this approach is better than it was before. The admin display
This is the biggest violation of the Single Responsibility principle. On the one hand it’s responsible for the AJAX requests. On the other hand it’s responsible for ALL the AJAX requests. It wouldn’t be difficult to break up. Next version.
Completely self-contained, hooks directly into
pre_serve_asset, does (almost) one thing.
create_log_table() into here, because it is a single function that is needed to make it work. It’s static so it can be accessed on plugin activation without instantiating the whole class.
My goal for this file was twofold:
- To implement wp.media.
Back when I first built this, wp.media didn’t exist. I implemented Plupload as a jQuery plugin in my original version. By using wp.media here I’m making the plugin “future proof.” If ever WordPress moves away from Plupload, they would implement whatever alternative via wp.media.
- To break apart big functions.
There was a huge spaghetti mess here before. Now that each “thing” is its own function I can iterate further in the next version.
This isn’t a finished product, nor is it the best I can do. But it’s a good step in the right direction. I learned a lot exploring what other people are doing with their plugins, and it was fun to flex my refactoring muscles to do this project. I hope you enjoyed, I did!
If you have any ideas about what steps you would want to see taken next, feel free to comment below, or use the contact form on the contact page.