Why I'm not the biggest WordPress fan

WordPress is an incredibly extensive system to create web contents, allowing you to build blogs, shops, portfolios or whatever - pretty much everything. This is awesome - so awesome that I can pay my bills by messing around with it. Nearly every website I've released was done with WordPress. Yet I'm not its biggest fan.

There are several reasons why I kinda dislike the biggest CMS out there.

Reason 1: Its "architecture"

There's a reason for putting the word architecture in quotation marks - WordPress doesn't have a (recognizable) architecture. It's literally just a big ball of mud.

A Big Ball of Mud is a haphazardly structured, sprawling, sloppy, duct-tape-and-baling-wire, spaghetti-code jungle. These systems show unmistakable signs of unregulated growth, and repeated, expedient repair. Information is shared promiscuously among distant elements of the system, often to the point where nearly all the important information becomes global or duplicated. [...]

That's exactly what it is. To give this statement a bit more details:

  • at some points its implementation is object oriented, at other points its procedural.
  • the code is not divided in (logic) parts, like you'd find it in a MVC pattern. No controllers for logic, no models for data and no view layer (and no template engine (nope, I don't count PHP itself as a template engine in 2016)). Business logic is spread over all files, just like you can find some "views" (which is just plain HTML) in "non-view files" (I don't even know how to call these files...).
  • no dependency management for the core. You either check in the whole thing or nothing. Same goes for plugins and themes. It's actually quite some work to make this happen.
  • namespacing is done by putting WP_ in front of class names. But not all classes are named this way (e.g. not wp-includes/wp-db.php).
  • to seperate classes and "non-class-files" class files are named class-wp-{classname}.php (e.g. wp-includes/class-wp-post.php). Sometimes also class.wp-{classname}.php (e.g. wp-includes/class.wp-styles.php). Or completely different, like wp-includes/date.php.
  • some things are written in more modern PHP, while others look like they come originally from the first beta.
  • it uses the global keyword. A lot. Like, a lot lot. Pretty much everything is - or at least should be - global. No matter if object oriented or procedural - you'll find globals.
  • it's inconsistent. If you think PHP is not inconsistent enough, WordPress will blast you even further.
  • it uses absolute paths, which are stored within your database. Migrating your site to another server means: search and replace your SQL! Wohoo...

Reason 2: It's big (and slow)

No matter if you're building a blog or a complex shop - WordPress is pretty big. Speaking in numbers (tested with a freshly installed WordPress v4.4.2 on a XAMPP with PHP v5.6.8 and mySQL v5.0.11):

CLOC

> cloc .

    1105 text files.
    1098 unique files.
     173 files ignored.

http://cloc.sourceforge.net v 1.56  T=7.0 s (150.4 files/s, 65201.9 lines/s)  
-------------------------------------------------------------------------------
Language                     files          blank        comment           code  
-------------------------------------------------------------------------------
PHP                            565          34741         100935         156557  
CSS                            167          15146           3541          75505  
Javascript                     319          10691          12728          46428  
HTML                             1             13              0             85  
XML                              1              6              0             37  
-------------------------------------------------------------------------------
SUM:                          1053          60597         117204         278612  
-------------------------------------------------------------------------------

It's important to note that these statistics do include the wp-content folder, and therefor the default plugin (namely Akismet) and three default wordpress themes (twentyfifteen, twentyfourteen and twentysixteen).

Looking just as the core of WordPress (by ignoring the wp-content directory) we get the following results:

> cloc . --exclude-dir=wp-content

     946 text files.
     946 unique files.
     346 files ignored.

http://cloc.sourceforge.net v 1.56  T=18.0 s (51.0 files/s, 23330.4 lines/s)  
-------------------------------------------------------------------------------
Language                     files          blank        comment           code  
-------------------------------------------------------------------------------
PHP                            469          33147          98151         149012  
CSS                            148          11465           2504          57824  
Javascript                     299          10385          12387          44932  
HTML                             1             13              0             85  
XML                              1              6              0             37  
-------------------------------------------------------------------------------
SUM:                           918          55016         113042         251890  
-------------------------------------------------------------------------------

Slightly smaller numbers, but using WordPress without plugins and especially themes is probably not the best thing you can do with it.

Memory usage

A total of 134 files is included before you can see something. Memory usage before WordPress is loaded is at 123.38 KB, whereas at the end it is at 12.03 MB. Thats a huge difference. And, especially in the world of PHP - where the interpreter is started separately for every single request - these 12 MB are pretty big.

Reason 3: Its code is... weird

Okay, here comes the fun part. Looking at each file separately would be a bit too much of work, but clicking through some files and point and the most ridiculous should also give a small glimpse of how WordPress is implemented.

Abstract methods are overrated

// wp-includes/class-wp-widget.php

public function widget( $args, $instance ) {  
    die('function WP_Widget::widget() must be over-ridden in a sub-class.');
}

That's the WordPress way of declaring a method abstract. Interestingly, this is not the regular case - there are some "real" abstract methods in, e.g., wp-includes/session.php:

abstract protected function get_sessions();  

var is ... private?

Back in times when I was way smaller, there was the var keyword in PHP. It was used for visibility - and is nothing else then public. Sometimes later the public, private and protected keywords were introduced. Sadly, as a non-PHP developer it's likely that you've got no idea what var does - and comments aren't that helpful in WordPress right there.

// wp-includes/class-json.php

// private - cache the mbstring lookup results..
var $_mb_strlen = false;  
var $_mb_substr = false;  
var $_mb_convert_encoding = false;  

That's wrong. These members are not private but public. It's getting even funnier since you'll find the public keyword in the same file:

/**
* PHP4 constructor.
*/
public function Services_JSON( $use = 0 ) {  

Which is also funny (it's like an endless loop of fun in this file), since the public keyword was introduced with PHP 5 - therefore a PHP 4 interpreter can't handle it anyways.

One last amusing side-fact, which has nothing to do with WordPress but PHP: var was declared deprecated in PHP 5.0.0 and "un-declared" deprecated in 5.1.3. Sigh...

"Sanity check"

Here come's one of my favorites; the "sanity check" from the installation.

// wp-admin/install.php

// Sanity check.
if ( false ) {  

Okay, uhm... I don't know. This condition checks for false and prints an error in case it's... true (which is probably never the case). The error itself says:

Error: PHP is not running

Here comes the real fun: you're not able to run a .php file if PHP is not running. You'll never see this error in case PHP is not running. But, okay, it's the thought that counts:

Reason 4: Theme-, plugin and templatehandling

WordPress has a weird way to handle themes and stuff like that. It finds them by looking for files called style.css. Interestingly this is not enough - this files first content has to be a comment block like

/*
Theme Name: gitsta  
Theme URI: https://github.com/nehalist/gitsta  
Author: Kevin Hirczy  
Author URI: http://nehalist.io  
[...]
*/

Same goes for plugins, which are also found by a comment block (this time within a .php file):

<?php  
/*
Plugin Name: Blub  
*/

And theme templates are - unsurprisingly - also found by comments:

<?php /* Template Name: Example Template */ ?>  

That's actually a pretty poor way of implementing this. These should be within one single and indenpendent file (something like theme.json / plugin.json or whatever). There are two major problems with the current implementation:

  • Finding themes by a .css file can cause some headache when using SASS.
  • Finding plugins and templates just by a single string within a file can cause duplication problems. For example: guess what happens if you're having the same template name twice within the same theme? Well, the second one found will simply be ignored (without a warning or any notification). It took some of my lifetime to find that out...

Reason 5: Its API is inconsistent.

Like the implementation of the core the "API" used for theme- und plugindevelopment is inconsistent. For example:

What does the_title() do? It prints the title of the current post. The arguments for this function are $before, $after and $echo. Pretty self explanatory arguments; $before is the text before the title, $after the text afterwards and $echo is a boolean which tells the function if it should print or return the title (printed title is displayed immediately while a returned statement needs to be printed with echo or something like that).

Okay, what does get_the_title() do? Kinda the same thing as the_title(), except it's taking just one argument (just $post) and always returns (never prints) the title of the provided $post object.

So far, so good. But what does get_search_form() do? Does it print or return the search form? The get_ prefix would lead to the assumption that it just returns the search form... which is wrong. It displays the search form. But, not always: the first and only argument of get_search_form() is $echo which could be used to disable printing the form.

It's getting a bit confusing. Let's take a look at another example: what about the_permalink()? Does it return or print? Does it have an $echo argument? Well, it echoes the link immediately - but doesn't have an argument to disable that. The only argument here is $post.

And what about the the_post()? Does a single function print a whole post? Nope. It's a void function which has nothing to do with displaying anything. It just sets the global $post object. It doesn't even have any arguments. Funnily, there's no get_the_post() - but a function called get_post(). get_post() returns data for a specific post.

The last one: get_header(). So we've learned that... there are a lot of the_, get_ and non-prefixed functions. So here's the question: what does get_header() do? Well, it includes your header file. No echoing here, no returning here - just a simple include. And there's no the_header() or get_the_header() or whatever.

Since I'm starting to confuse myself by looking through the code reference and looking for inconsistencies I'm going to stop here. I guess everyone gets the point: its API is inconsistent.

Reason 6: It shows people how to do it wrong

This is - IMHO - the most serious problem: it teaches things wrong.

One of the biggest advantages of open source is its ability to teach. Since you've got the freedom of just looking right under the hood you may learn - directly or indirectly - from it. You've got a huge documentation, tons of resources - but how useful can this be, if most of it is outdated or - in the case of WordPress - just terribly wrong?

Lots of people who want to dive into Webdevelopment may start with WordPress. Since they have no idea of how things are done, WordPress is their first impression, their first reference. Throughout the years they probably stay with WordPress and get used to the techniques used in WordPress.

And that's the problem of WordPress. Some things are just implemented in a very shitty way, e.g.:

  • globals? NP, just use them everywhere. Why should they be bad?
  • design patterns? Nah, no need!
  • database consistency? Like foreign key constraints and things like that? What?
  • dependency management? Why use things like Bower or Composer for webprojects? What an overkill!
  • javascript frameworks? Just use jQuery (and jQuery plugins), for AJAX calls, templating, everything!
  • and more...

I've worked with a bunch of people who work with nothing but WordPress. They made some themes for it, maybe plugins. And some of these source codes were the most fucked up things I've ever seen.

Conclusion

WordPress has its flaws (like every bigger system out there). A lot of them. It's uncontrolled growth led to what it is nowadays: a huge piece of software without architecture, an inconsistent API and all these fun stuff.

Todays websites are more than they used to be back then when WordPress was released. You still can do every kind of website today with WordPress - the price for this diversity are some of the points mentioned in this post.

So is not using WordPress an option?

Probably not. It probably won't get any better for developers - but it's what brings the money. There are ways to improve WordPress development (more precisely: ways to make theme/plugin developers life easier), e.g. theme or plugin development frameworks, boilerplates, etc.. Use them. Seriously.

But don't use WordPress as a reference. Don't adapt its weird characteristics, don't use it when it comes to clean code, don't learn too much from it. It may bring you money, but it definitely doesn't make you a better developer.