How to keep your WordPress theme clean

More than once when I look at WordPress themes I see a lot of disorganised code. This varies from functions.php -files with hundreds lines of code that are a mixture user-specified functions and WordPress-specific functions (add_filter() , add_action() , etc). Also the templates files themselves are more often a complete mixture of HTML and massive blocks of PHP-code. Even the default theme that ships with WordPress is setup like this so you could say that WordPress encourages to create your themes in this manner. In this article I’m going to share with you a different approach on how to setup your WordPress theme in a clean way.

Concatenate your template in a class

To prevent putting a lot of disorganised code in your functions.php, consider putting your theme-specific functions inside a separate class. This class can contain functions for initialisation, as well as taking care of some theme-specific hooks. Lets put this file in inc/MyTheme.php :

PHP

1

2

3

4

5

6

7

8

9

10

11

12

classMyTheme

{

publicfunction__construct()

{

// Register menus:

register_nav_menu('primary','Primary Menu');

register_nav_menu('footer','Footer Menu');

}

}

// Autoload this class on inclusion:

newMyTheme();

Now in our functions.php , we include this class:

PHP

1

require_once('inc/MyTheme.php');

Now our functions.php -file is nice and tidy, and our theme-logic can be put in it’s own file.

Use separate classes for different purposes.

At this point, you might be wondering: ‘why is this better than just placing everything in functions.php?’. Let me show you just how we are now about to organise our code by using separate classes for different purposes. Let’s say that we want to add some extra functionality to our pages. For example, add thumbnail / featured image support to pages. You might be tempted to add this functionality to your functions.php -file. But let us instead create a new class in inc/MyTheme_Page.php :

PHP

1

2

3

4

5

6

7

8

9

10

11

12

13

classMyTheme_Page

{

/**

* Constructor

*/

publicfunction__construct()

{

// Add support for featured images:

add_theme_support('post-thumbnails',array('post','page'));

}

}

newMyTheme_Page();

See how we separated the adjustment for pages from our theme functionality? Now this is a very basic example, but can you imagine when you want to add more functionality to pages? Like adding extra metaboxes or actions? This way you can concatenate all the logic you do for pages in one single file. For example, when we want to add some extra metaboxes, we could do something like this:

PHP

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

classMyTheme_Page

{

/**

* Constructor

*/

publicfunction__construct()

{

// Add support for featured images:

add_theme_support('post-thumbnails',array('post','page'));

// Add actions:

add_action('add_meta_boxes',array($this,'addMetaBoxes'));

add_action('save_post',array($this,'savePost'));

}

/**

* Function to add meta boxes

*/

publicfunctionaddMetaBoxes()

{

// logic to add meta boxes

}

/**

* Save Post

*

* @param int $postId

*/

publicfunctionsavePost($postId)

{

// logic when saving a post

}

}

newMyTheme_Page();

The same logic can be applied to other post types or your own custom post types. Also note how we can specify array($this, ‘functionName’) to set a function inside this class as a callback. This way we can use generic names for functions that are used in multiple post types so they are setup in a generic way.

Use static methods in templates

WordPress templates can get bloated very quickly. This is because they are a complete mixture of HTML and PHP where PHP tends to get the upper hand quickly. Take this piece of template for example:

PHP

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

<article>

<pclass="category"><?php

$categories=get_the_category();

if(count($categories)>0){

echo$categories[0]->name;

}?></p>

<h1><?phpthe_title();?></h1>

<h3><?php$more=false;

the_content(false);

$more=true;?></h3>

<pclass="date"><?phpthe_date();?></p>

<?php$content=get_the_content(null,true);

$content=apply_filters('the_content',$content);

$content=str_replace(']]>',']]>',$content);

// Remove the empty paragraph with the <span id="more-.."></span>-tag:

This template is a perfect example of how PHP can take the upper hand in this template. I mean, almost 90% of this piece of code is PHP! Now, let’s separate the PHP logic into our template class. Then our template class is going to look something like this:

PHP

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

classMyTheme

{

publicfunction__construct()

{

// Register menus:

register_nav_menu('primary','Primary Menu');

register_nav_menu('footer','Footer Menu');

}

/**

* Get the name of the first category

*

* @return string

*/

publicstaticfunctiongetCategoryName()

{

$categories=get_the_category();

if(count($categories)>0){

return$categories[0]->name;

}

return'';

}

/**

* Echo the content before the <!--more--> tag

*/

publicstaticfunctiongetContentBeforeMore()

{

global$more;

$more=false;

the_content(false);

$more=true;

}

/**

* Echo the content after the <!--more--> tag

*/

publicstaticfunctiongetContentAfterMore($removeMoreTag=true)

{

$content=get_the_content(null,true);

$content=apply_filters('the_content',$content);

$content=str_replace(']]>',']]&gt;',$content);

// Remove the empty paragraph with the <span id="more-.."></span>-tag:

Now, from a template point of view this looks far more lean and clean. You keep touch of your HTML-structure and PHP-logic is separated in the therefore destined class. Working in this way also makes it more easier to split tasks to separate developers: one developer can work on the templates, while the other one makes sure the theme-specific functions work. So that’s all there’s to it. I hope this article helps you in writing leaner, cleaner and better manageable templates. Happy templating!

2 thoughts on “How to keep your WordPress theme clean”

Great tips, Giel. Only wish more people would do anything remotely close to this. The thing I was talking about last friday was: Timber. Which looks very interesting too. Creates an even larger gap between logic and templates.

Looks good. Although I totally agree with you that WordPress’ way of ‘templating’ is ugly and inconvenient as hell, I’m also wondering what cans of worms solutions like Timber are going to cause with 3rd party plugins, or integration with plugins-that-are-more-than-plugins like WooCommerce or BuddyPress. Do you have any experience with that?

This is the blog Giel Berkers,
a fulltime web developer from The Netherlands with a passion for the web.
I want to share ideas, knowledge, but also learn from
my readers. If you got any questions, or need help with something, feel free to drop me a
line.If I think that more people can benefit from the answer on your question, I'll write a blog post about it.