Zach Owen, Author at WebDevStudios https://webdevstudios.com/author/zach/ WordPress Design and Development Agency Mon, 15 Apr 2024 16:04:02 +0000 en-US hourly 1 https://wordpress.org/?v=6.6.2 https://webdevstudios.com/wp-content/uploads/2022/07/cropped-wds-icon.white-on-dark-60x60.png Zach Owen, Author at WebDevStudios https://webdevstudios.com/author/zach/ 32 32 58379230 Debugging WordPress with Local by Flywheel, (neo)vim, and xdebug https://webdevstudios.com/2019/04/16/debugging-wordpress-with-local-by-flywheel-neovim-and-xdebug/ https://webdevstudios.com/2019/04/16/debugging-wordpress-with-local-by-flywheel-neovim-and-xdebug/#respond Tue, 16 Apr 2019 16:00:53 +0000 https://webdevstudios.com/?p=20143 Introduction Local by Flywheel is a popular tool for getting quick and reliable WordPress installations running on your computer. One of its lesser-known features is the inclusion of xdebug support. xdebug is a PHP extension that allows for real-time debugging of PHP code. Today, we’re going to go over how to get both of these Read More Debugging WordPress with Local by Flywheel, (neo)vim, and xdebug

The post Debugging WordPress with Local by Flywheel, (neo)vim, and xdebug appeared first on WebDevStudios.

]]>
Introduction

Local by Flywheel is a popular tool for getting quick and reliable WordPress installations running on your computer. One of its lesser-known features is the inclusion of xdebug support. xdebug is a PHP extension that allows for real-time debugging of PHP code. Today, we’re going to go over how to get both of these working together within vim to provide a powerful interface that allows for some successful debugging of WordPress.

Prerequisites

Firstly, this tutorial is intended for users of vim or neovim. If you aren’t familiar with how to use vi-like editors, but want to learn, I would recommend running vimtutor in your command line and learning how to move and work in vim before continuing with this post.

Next, you’ll need Local by Flywheel. You can download it here. If you haven’t set up a site before with Local, it is pretty straightforward. You can find a guide for getting started on Flywheel’s blog.

Setup

vim

For vim or neovim, henceforth referred to simply as “vim” (with distinctions for neovim if necessary), you will need the Vdebug plugin. Installation instructions are included on the plugin’s page. I use vim-plug to manage plugins; so my .vimrc looks like this:

""" Vim-Plug
call plug#begin()
Plug 'vim-vdebug/vdebug'
call plug#end()

After adding Vdebug, we’ll need to add some configuration. Before we continue, let’s get Local configured for xdebug.

Local and xdebug

Local ships with the xdebug extension available but not enabled. Each site that you want to debug will need its configuration altered to work with debugging. First, find your Local site site’s directory. In Local, you can view this on the Overview tab, under “Site Path.”

Open your site’s directory, and find the file conf/php/<your site's PHP version>/php.ini. Open this file with any text editor and find the section titled [Xdebug]. This contains the relevant configuration we’re looking for. After modifying this section, your section should look similar to:

xdebug.remote_enable=1
xdebug.remote_connect_back=On
xdebug.remote_port="9000"
xdebug.profiler_enable=1
xdebug.remote_autostart=true
xdebug.remote_handler=dbgp
xdebug.remote_mode=req
xdebug.remote_host=<your local IP>

Note that the remote_host argument should be your computer’s local IP. This will allow the Local machine to talk to your editor.

Save your modifications, and restart your site in Local.

Configuring vim

Open your vim configuration file. Typically, for vim, this will be ~/.vimrc, in NeoVim, your configuration is usually in ~/.config/nvim/init.vim. Add a new section to your vimrc that looks like this:

let g:vdebug_options= {
    "port" : 9000,
    "server" : '',
    "timeout" : 20,
    "on_close" : 'detach',
    "break_on_open" : 0,
    "ide_key" : '',
    "path_maps" : {
        '/app/public/': '<path to your project public folder>'
    },
    "debug_window_level" : 0,
    "debug_file_level" : 0,
    "debug_file" : "",
    "watch_window_style" : 'compact',
    "marker_default"     : '⬦',
    "marker_closed_tree" : '▸',
    "marker_open_tree" : '▾'
}

Note that you need to fill in the path_map item with your local project’s public folder. If your project is located in /Users/you/Local/myproject/, your public folder would be in /Users/you/Local/myproject/app/public/. Also note that the left-hand side points to /app/public/. This is where Local’s server stores your public files. The right-hand side points to the location of the files as you see them in your filesystem.

Now, save your vim configuration and restart vim (you can probably source the configuration, but Vdebug can be a little weird sometimes). Open a file in your project. Let’s try wp-config.php to start. Find a line with code before wp-settings.php is included and press <F10> on your keyboard.

The line should change color. In my editor, it shows a green line where I set the breakpoint:

Now, press <F5> and you should see a message in the status line saying that “Vdebug will wait for a connection in the background.” Visit any page in your site, and you should see Vdebug connect and pause on the line you set as a breakpoint:

Troubleshooting

Here are some tips if you’re having trouble with Vdebug:

  • If the debugger is attaching and then stopping, verify the path_maps configuration.
  • If the debugger is not attaching, verify your Xdebug configuration in your php.ini.

Working with the Debugger

Author note: the following code takes place in the twentynineteen theme. The premise of this exercise is ridiculous, and meant to be an example of how to use the debugging functionality.

Vdebug includes a number of default key mappings, as well as some commands to help evaluate your code. Open your theme’s functions.php and add the following:

add_filter( 'the_content', function( $content ) {
    if ( is_admin() ) {
        return $content;
    }

    return str_rot13( $content );
} );

Now, travel to a single post on your site’s frontend, and view a post:

Whoops, seems something has gone wrong! Let’s suppose this code is buried somewhere deep in our included files; it could be a pain to find the source of this issue. With xdebug, we can trace the code back to our bad filter—the one that we “totally don’t know about…”

First, open up template-parts/content/content-single.php, and find the line calling the_content:

23         the_content(
24             sprintf(
25                 wp_kses(
26                     /* translators: %s: Name of current post. Only visible to screen readers */
27                     __( 'Continue reading<span class="screen-reader-text"> "%s"</span>', 'twentynineteen' ),
28                     array(
29                         'span' => array(
30                             'class' => array(),
31                         ),
32                     )
33                 ),
34                 get_the_title()
35             )
36         );

Since we know our issue is in the content being output, move your cursor on the line with the call to the_content and press <F10> on your keyboard. The line should highlight to indicate that you have set a breakpoint.

Before continuing, it’s a good time to review some of Vdebug‘s key mappings from the Quick Guide section of the README:

<F5>: start/run (to next breakpoint/end of script)
<F2>: step over
<F3>: step into
<F4>: step out
<F6>: stop debugging (kills script)
<F7>: detach script from debugger
<F9>: run to cursor
<F10>: toggle line breakpoint
<F11>: show context variables (e.g. after "eval")
<F12>: evaluate variable under cursor
:Breakpoint <type> <args>: set a breakpoint of any type (see :help VdebugBreakpoints)
:VdebugEval <code>: evaluate some code and display the result
<Leader>e: evaluate the expression under visual highlight and display the result

We will primarily be focused on <F5>, <F3>, <F4>, <F9>, and <F10>. Remember, if you get lost, you can always press <F6> to quit the debugger and then start again.

Next, to start the debugger, press <F5>. You should see the following message in your status line: “Vdebug will wait for a connection in the background.” Reload the page in your browser and you should be presented with the debugging window.

The debugger should halt on our breakpoint. From here, we’ll want to “step into” the function calls to decipher what’s going on using <F3>. When we first step in, you’ll notice we’re not inside the_content, but __. What’s going on? PHP executes methods from the innermost function call to the outermost. Since our breakpoint is actually on a set of nested function calls, we’ll need to press <F4> to step out” of each function until we get to the_content:

Once we’re in the content, we can see a call to apply_filters. Knowing how WordPress works with Actions and Filters, it’s a safe bet that our content is being modified in a filter. Move your cursor to the line calling apply_filters, and press <F9> to allow the program to run until we get to that line.

Next, press <F3> to step into apply_filters. I’ll tell you, this function is a little confusing. We just want to worry about the line that actually calls the filter methods:

    $filtered = $wp_filter[ $tag ]->apply_filters( $value, $args );

Put your cursor on that line and press <F9> again, and then “step in” with <F3>. As you enter the apply_filters method, bear in mind that the crux of WordPress hooks are callbacks. With that in mind, it’s safe to say the following lines are where the magic happens:

282                 // Avoid the array_slice if possible.
283                 if ( $the_['accepted_args'] == 0 ) {
284                     $value = call_user_func_array( $the_['function'], array() );
285                 } elseif ( $the_['accepted_args'] >= $num_args ) {
286                     $value = call_user_func_array( $the_['function'], $args );
287                 } else {
288                     $value = call_user_func_array( $the_['function'], array_slice( $args, 0, (int)$the_['accepted_args'] ) );
289                 }

Lines 284, 286, and 288 all use call_user_func_array in some form or fashion. Place your cursor on each line and press <F10> to add a breakpoint, and then hit <F5> to continue execution. The debugger will begin breaking on one of those three lines.

The Watch Window

Vdebug displays a window where you can watch the variables that are available in various scopes. By default, the “Locals” scope is shown.

This is a window just like any other vim window. Move your cursor to the Locals window, and scroll down until you find the $the_ array (hint: you can search with normal vim commands); expand it by using the <Enter> key. Next, you should look at the value of $the_["function"]. Notice that this will either be an array or a string. Expand the array or view the string with each run of <F5>, looking for anything that may stick out as odd.

Did you find it? There’s a Closure. Since we can’t see what it does here, we’ll need to “step in” again with <F3>. The debugger now drops us into the offending method—the filter we added earlier calling str_rot13.

Wrapping Up

With this ridiculous example, I hope you are able to use xdebug in your own projects to effectively debug. Understanding the WordPress codebase is crucial to being an effective developer, and getting down and dirty with a debugger is a great way to learn how truly complex a system can be.

Tips

  • Vdebug can be fickle – you may need to hit <F6> a couple of times to close the debugger completely.
  • Use :help Vdebug and read the documentation to learn about things like <leader>e.
  • Use project-specific .vimrc files to set up your Vdebug paths:

In the following examples, use .vimrc for vim and init.vim for neovim:

" In your ~/.vimrc or ~/.config/nvim/init.vim
set exrc " see :help exrc

" At the BOTTOM of your RC file:
set secure

This will allow you to set up a configuration for each project. vim with search for either .vimrc, _vimrc, or .exrc in your current directory and load it if found. For neovim, the file names are .nvimrc, _nvimrc, and .exrc. I tend to work from the wp-content folder to make use of tags for my plugins and themes. Depending on where you start your editing, place your RC file in the appropriate location and add your vdebug_options configuration in there. Here’s mine in ~/src/WDS/local/lab/app/public/wp-content/.nvimrc:

" Local 'Lab' {{{
let g:vdebug_options= {
    "port" : 9000,
    "server" : '',
    "timeout" : 20,
    "on_close" : 'detach',
    "break_on_open" : 0,
    "ide_key" : '',
    "path_maps" : {
        '/app/public/': '/Users/phatsk/src/WDS/local/lab/app/public/'
    },
    "debug_window_level" : 0,
    "debug_file_level" : 0,
    "debug_file" : "",
    "watch_window_style" : 'compact',
    "marker_default"     : '⬦',
    "marker_closed_tree" : '▸',
    "marker_open_tree" : '▾'
}
" }}}

Now, I don’t have to worry about resetting things in my init.vim whenever I switch projects!

Actual Conclusion

You made it! In this post you (hopefully) learned:

  • How to enable xdebug in your Local installations
  • Install the Vdebug plugin for neo/vim
  • Effectively use Vdebug to track down bugs in code.

Happy bug squashing!

The post Debugging WordPress with Local by Flywheel, (neo)vim, and xdebug appeared first on WebDevStudios.

]]>
https://webdevstudios.com/2019/04/16/debugging-wordpress-with-local-by-flywheel-neovim-and-xdebug/feed/ 0 20143
Debugging WordPress Core: Actions and Filters https://webdevstudios.com/2019/01/22/debugging-wordpress-core-actions-filters/ https://webdevstudios.com/2019/01/22/debugging-wordpress-core-actions-filters/#comments Tue, 22 Jan 2019 17:00:39 +0000 https://webdevstudios.com/?p=19386 Most WordPress developers are familiar with the concept of actions and filters. At the very heart of WordPress, these hooks allow developers to extend the functionality of WordPress in numerous ways. Whether you want to run a process when a post is saved, add a new section to the Edit User page, or modify the Read More Debugging WordPress Core: Actions and Filters

The post Debugging WordPress Core: Actions and Filters appeared first on WebDevStudios.

]]>
Most WordPress developers are familiar with the concept of actions and filters. At the very heart of WordPress, these hooks allow developers to extend the functionality of WordPress in numerous ways. Whether you want to run a process when a post is saved, add a new section to the Edit User page, or modify the SQL used when querying the database, WordPress has hooks for (almost) everything.

One thing I’ve noticed a lot, as a frequent user of the WordPress StackExchange, is that many developers don’t know where to start when trying to figure out which actions or hooks might be available to them. In this blog post, I want to help walk through the process of tracking down various hooks with examples of when you might want to use them and how to implement them.

Actions and Filters: What’s the Difference?

This is a very basic mistake I see often when helping people figure out their WordPress issues. Say for example someone wants to modify the post before editing, but they can’t figure out why their code isn’t doing anything. Well, let’s take a look at a basic example that makes a post’s content all-uppercase:

add_action( 'content_edit_pre', function( $post_content ) {
	return strtoupper( $post_content );
} );

Pretty straightforward, right?

GIF animation of a panicked man in front of a blazing fire.

On the surface, this looks like a proper filter but it will never work. The reason is that WordPress makes a distinction between actions and filters. Actions are assigned via add_action, while filters are assigned via add_filter. The corresponding methods to call these are do_action and apply_filters, respectively. Under the hood, there’s actually not much difference. In fact, add_action calls add_filter. Here’s the full source code from WordPress:

function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
    return add_filter($tag, $function_to_add, $priority, $accepted_args);
}

Kind of crazy, right?

It’s because add_filter and add_action do roughly the same thing at the core level, with one minor exception: the returned value of apply_filters can be used to modify existing data structures, while do_action returns literally nothing (void in PHP).

So, our above example will never return any value to modify the content, as do_action simply doesn’t do that. While these differences may make you want to ask, “Why even have different methods?” the distinction is very important.

Actions are for when you want something to happen as a result of something else happening, while filters are used to modify data at run time. Our above example will work with the exact same code, with one minor modification:

add_filter( 'content_edit_pre', function( $post_content ) {
	return strtoupper( $post_content );
} );

[Edit: thanks @Anton Serednii for the correction!]
In WordPress-speak, we use the term “hook” to refer to actions and filters interchangeably, as they are roughly the same thing. When talking about a specific hook, we use either action or term. (Example: “You want to use the admin_enqueue_scripts action to add scripts to WP Admin,” or, “You can use the body_class filter to add additional CSS classes to a page’s <body> tag.”)

Finding the Right Hook

WordPress has a lot of hooks to use. I mean, a lot. A rough count of the WordPress codebase puts the number of hooks called at around 2,744. That’s a lot of hooks!

A GIF animation of Dustin Hoffman as Captain Hook.

 

So, how do you find the right one? Well, you can refer to the action and filter references linked above (and also check out the Plugin API landing page), but those references cover everything and, as we just discussed. That’s a lot of things.

Furthermore, some of the hooks are still undocumented to this day in the Codex. In some cases, the best way is to identify the method that you want to hook into and then check it out in the source code. Additionally, you might learn some interesting things about the hooks once you dive into where they are called from.

Example 1: The save_post Action

The save_post action is triggered by wp_insert_post and wp_publish_post. Both methods are defined in wp-includes/post.php. If we dig into the source code, we’ll first find this definition of save_post:

/**
 * Fires once a post has been saved.
 *
 * @since 1.5.0
 *
 * @param int $post_ID Post ID.
 * @param WP_Post $post Post object.
 * @param bool $update Whether this is an existing post being updated or not.
 */
do_action( 'save_post', $post_ID, $post, $update );

What’s interesting here is that directly above it we can also see this:

/**
 * Fires once a post has been saved.
 *
 * The dynamic portion of the hook name, `$post->post_type`, refers to
 * the post type slug.
 *
 * @since 3.7.0
 *
 * @param int $post_ID Post ID.
 * @param WP_Post $post Post object.
 * @param bool $update Whether this is an existing post being updated or not.
 */
do_action( "save_post_{$post->post_type}", $post_ID, $post, $update );

That’s neat! We can actually target save_post for our own specific post type. This saves a few lines of doing a check like this:

if ( 'my_custom_post_type' !== $post->post_type ) {
    return;
}

Another important note when it comes to hooks is not to hook something that might bite you later. For example, save_post is a great action to use when you want to do something after a post saves. For instance, you might want to record a new post entry for your publish_log custom post type that tracks when posts are published. Let’s take a look at an example:

function maybe_create_publish_log( $post_id, $post ) {
    if ( 'publish' !== $post->post_status ) {
        return;
    }

    wp_insert_post( [
        'post_type' => 'publish_log',
        'post_author' => $post->post_author,
        'post_status' => 'publish',
        'post_content' => "New post {$post->post_title} published on {$post->post_date}.",
        // etc...
    ] );
}

add_action( 'save_post', 'maybe_create_publish_log', 10, 2 );

At first glance, this seems fine. But remember earlier when we learned that save_post is called by wp_insert_post? With this code, you might find yourself creating tons of  publish_log posts because your hook to save_post is being called over and over by wp_insert_post. So, how do you get around this?

The answer is the aptly named remove_action (if you guessed that its sister function is remove_filter and that remove_action simply calls remove_filter, you get a cookie). Let’s take a look at our code now:

function maybe_create_publish_log( $post_id, $post ) {
    if ( 'publish' !== $post->post_status ) {
        return;
    }

    remove_action( 'save_post', 'maybe_create_publish_log' );
    wp_insert_post( [
       'post_type' => 'publish_log',
       'post_author' => $post->post_author,
       'post_status' => 'publish',
       'post_content' => "New post {$post->post_title} published on {$post->post_date}.",
        // etc...
    ] );
    add_action( 'save_post', 'maybe_create_publish_log', 10, 2 );
}

add_action( 'save_post', 'maybe_create_publish_log', 10, 2 );

This is one of the benefits to diving into the core files: if you look up where your action is called from, you will know if you’re about to get into a publishing loop, or avoid other possible “gotchas” when developing your plugins and themes.

Example 2: Modifying the Edit User Screen

Recently at WebDevStudios, we’ve had a couple of clients that needed specific sections added to the user profile page. You may be looking to integrate a service, such as Medium, to your user accounts, or you may want to give administrators the ability to modify fields specific to a plugin. But where do you start?

If you look in the action reference, well, you might be looking for a long time. You’d eventually find what you’re looking for, but there is an easier way.

First, on a WordPress install, you’ll notice you’re at this page when editing a User: /wp-admin/user-edit.php?user_id=3. If you’re editing your own user, you’ll find that you’re at /wp-admin/profile.phpYou might be thinking, “Oh geez, I have to dig into two files to find the action I want?!”

But fear not, because upon opening profile.php you’ll see it’s actually rather simple:

<?php
/**
 * User Profile Administration Screen.
 *
 * @package WordPress
 * @subpackage Administration
 */

/**
 * This is a profile page.
 *
 * @since 2.5.0
 * @var bool
 */
define('IS_PROFILE_PAGE', true);

/** Load User Editing Page */
require_once( dirname( __FILE__ ) . '/user-edit.php' );

Well, that saves us some time. Now, if you dig into user-edit.php, you’re going to be looking for calls to do_action. Let’s do a quick check with ag – the silver searcher:

  ag do_action wp-admin/user-edit.php

Which gives us the following output:

132: do_action( 'personal_options_update', $user_id );
141: do_action( 'edit_user_profile_update', $user_id );
230: do_action( 'user_edit_form_tag' );
285: do_action( 'admin_color_scheme_picker', $user_id );
347:do_action( 'personal_options', $profileuser );
362: do_action( 'profile_personal_options', $profileuser );
658: do_action( 'show_user_profile', $profileuser );
667: do_action( 'edit_user_profile', $profileuser );

Now, let’s dig into the actual file itself. Odds are we want to be looking at edit_user_profile specifically:

if ( IS_PROFILE_PAGE ) {
	/**
	 * Fires after the 'About Yourself' settings table on the 'Your Profile' editing screen.
	 *
	 * The action only fires if the current user is editing their own profile.
	 *
	 * @since 2.0.0
	 *
	 * @param WP_User $profileuser The current WP_User object.
	 */
	do_action( 'show_user_profile', $profileuser );
} else {
	/**
	 * Fires after the 'About the User' settings table on the 'Edit User' screen.
	 *
	 * @since 2.0.0
	 *
	 * @param WP_User $profileuser The current WP_User object.
	 */
	do_action( 'edit_user_profile', $profileuser );
}

You’ll notice that I copied out the surrounding if conditional. As well, you might notice something familiar on the first line: the if ( IS_PROFILE_PAGE ) check lets you hook in just on your own user page, or only on other users’ pages, or both by a combination of both actions.

With these actions, we can render a custom set of fields to modify the user edit page and bring custom functionality right into the core of WordPress. While the Codex’s action list is quite extensive and sometimes difficult to navigate, it is a wonderful resource for finding additional information on most actions and filters once you know what to look for. Have a peek at the page for edit_user_profile, for example.

Example 3: Modifying Query SQL with Filters

This is a slightly more advanced example, but an important one. WordPress does a lot of things under the hood to construct the MySQL queries that ultimately find your posts, tags, etc. Let’s start with an example WP Query from get_posts:

$args = [
    'post_type'      => 'post',
    'posts_per_page' => 5,
    'orderby'        => 'post_date',
    'order'          => 'ASC',
    's'              => 'Test',
];

$posts = get_posts( $args );

The resulting SQL looks something like this:

SELECT
    wp_posts.ID
FROM
    wp_posts
WHERE 1=1
AND (((wp_posts.post_title LIKE '%Test%') OR (wp_posts.post_excerpt LIKE '%Test%') OR (wp_posts.post_content LIKE '%Test%')))
AND (wp_posts.post_password = '')
AND wp_posts.post_type = 'post'
AND ((wp_posts.post_status = 'publish'))
ORDER BY wp_posts.post_date ASC
LIMIT 0, 5

This query, although simple, is filtered several times before it is passed to the database for record retrieval. A quick aside—the “%” signs may be encoded as long hashes when you view the query, as a placeholder to help with how $wpdb parses placeholders.

Next, we’ll step through some of the more useful filters used. The following code can be found in wp-includes/class-wp-query.php. 

posts_where

This is one of the earliest filters on the query, and filters the WHERE clause of the query. For the above example, this filter’s parameters are the WHERE clause as the first parameter, and a reference to the query object as the second. The WHERE clause looks like this:

    [0] =>  AND (((wp_posts.post_title LIKE '{67feda5925d0533a58f19e45c96ff1c761ddaa2263949b4ae0023a90b3f25b1f}Test{67feda5925d0533a58f19e45c96ff1c761ddaa2263949b4ae0023a90b3f25b1f}') OR (wp_posts.post_excerpt LIKE '{67feda5925d0533a58f19e45c96ff1c761ddaa2263949b4ae0023a90b3f25b1f}Test{67feda5925d0533a58f19e45c96ff1c761ddaa2263949b4ae0023a90b3f25b1f}') OR (wp_posts.post_content LIKE '{67feda5925d0533a58f19e45c96ff1c761ddaa2263949b4ae0023a90b3f25b1f}Test{67feda5925d0533a58f19e45c96ff1c761ddaa2263949b4ae0023a90b3f25b1f}')))  AND (wp_posts.post_password = '') 

Two notes about the above: first, you can see the expanded version of the placeholder for the “%” symbol. Second, the query clause starts with an AND. You may have noticed in the original query that this clause starts with WHERE 1=1. This is a simple trick to allow adding more conditions to the WHERE clause. If we wanted to add an extra field to check against when someone searches, say from another table, we could do something like this:

add_filter( 'posts_where', function( $where, $query ) {
    if ( 'post' !== $query->get( 'post_type' ) {
        return $where;
    }

    if ( ! $query->get( 's' ) ) {
        return $where;
    }

    $search = $query->get( 's' );
    $where .= " AND mycustomtable.ad_keywords LIKE '%{$search}%'";
    return $where;
}, 10, 2 );

This would allow us to search across our custom table for rows with a matching search in the ad_keywords column. If you’re familiar with SQL, you’re probably wondering how we’re querying the mycustomtable table without a JOIN. Well, right below the call to filter posts_where is our next guest…

posts_join

The posts_join filter allows us to write JOIN clauses to other tables we might need in our query. Currently, our query doesn’t join to any other tables since we aren’t doing a taxonomy query or meta query. However, if we want to JOIN our custom table, it’s pretty straight forward.

add_filter( 'posts_join', function( $joins, $query ) {
    if ( 'post' !== $query->get( 'post_type' ) {
        return $joins;
    }

    if ( ! $query->get( 's' ) ) {
        return $joins;
    }

    $joins .= 'JOIN mycustomtable ON( wp_posts.ID = mycustomtable.post_id )';
    return $joins;
}, 10, 2 );
Other Filters

While the above two filters make up the bulk of useful filters for most cases, the following may also be relevant depending on your use-case:

  • posts_where_paged and posts_join_paged – Similar to the above two filters, but used expressly when pagination is concerned
  • posts_orerby – Direct access to the ORDER BY clause, responsible for the order in which your posts appear when queried
  • post_limits – The query’s LIMIT clause
  • posts_fields – Determines which fields are returned from the database (note that WordPress does a lot of this for you when it gets the actual post objects, typically you wouldn’t need to modify this outside of very specific use-cases)
  • posts_clauses – This is kind of a catchall for various parts of the query, including WHERE, GROUP BY, JOIN, ORDER BY, DISTINCT, selected fields, and LIMIT.

Conclusion

With the above, I hope you have a better understanding of how and where WordPress filters certain things, and I hope you go off and explore the codebase the next time you say, “Geez, I really wish I could modify that!” WordPress has plenty of actions for developers to tap into once you know where to look. Happy coding!

The post Debugging WordPress Core: Actions and Filters appeared first on WebDevStudios.

]]>
https://webdevstudios.com/2019/01/22/debugging-wordpress-core-actions-filters/feed/ 3 19386
Introduction to End-to-End Testing with Cypress.io https://webdevstudios.com/2018/11/13/end-to-end-testing-with-cypress-io/ https://webdevstudios.com/2018/11/13/end-to-end-testing-with-cypress-io/#respond Tue, 13 Nov 2018 17:00:31 +0000 https://webdevstudios.com/?p=19366 The topic of testing comes up often at WebDevStudios—whether we’re on-boarding a new project, or we’re digging out bugs on existing work, and even when we talk about our own internal tools. Testing is a common part of software development that often gets overlooked, especially when you consider a website that might be more “static,” Read More Introduction to End-to-End Testing with Cypress.io

The post Introduction to End-to-End Testing with Cypress.io appeared first on WebDevStudios.

]]>
The topic of testing comes up often at WebDevStudios—whether we’re on-boarding a new project, or we’re digging out bugs on existing work, and even when we talk about our own internal tools. Testing is a common part of software development that often gets overlooked, especially when you consider a website that might be more “static,” such as a WordPress blog. But regardless of whether your site is running a rich web application or serving up your favorite recipes to your readers, End-to-End (E2E) testing has benefits for everyone.

Today, I’m going to walk through getting started with Cypress.io—a JavaScript-based E2E platform that’s easy to get up and running and is powerful in numerous ways that could make you rethink testing.

What Exactly is “End-to-End Testing?”

End-to-end testing means testing your application in a way that each component, from start to finish, is tested to do what it’s supposed to do. As an example, imagine a website that has a “Contact Us” form. Testing this would mean filling out the form, clicking the submit button, and expecting to see a result afterwards of something along the lines of “Thank you for contacting us.”

This is a simple example; other examples include testing a Single Page Application, or a complex search with filtering and sorting. These kinds of tests aren’t hard for an individual to do, certainly, but as people, we’re prone to mistakes. Maybe you forget to see what happens if a checkbox is toggled on or off, or you don’t remember to try filtering a list after sorting to see if the sorted state remains after filtering.

With a testing suite, you can write tests that are both descriptive and repeatable. This helps us remember what we’re testing and ensures that with every iteration of a site or application, we can know what tests to run. Cypress also provides the ability to “step through” your tests after they complete, allowing you to see the application’s state at any given point as it was when the test was running.

Example of Cypress running the actions sample spec

The above GIF shows the Cypress sample test spec called “actions.spec.js.” You can see that Cypress opens its own browser, runs your tests, and allows you to jump to any point in the test history and see the application state as it was right then. Awesome, right?

Getting Started

You can find out detailed instructions for getting started with Cypress on their Installing Cypress page. For the purposes of this post, I’m not going to go into great detail, but I will walk through the simplest installation method and one most people are likely familiar with: the Node Package Manager. Before going any further, it’s important to note the system requirements for Cypress as of the time of this writing:

  • Mac OS 10.9+ (Mavericks+), only 64bit binaries are provided for macOS
  • Linux Ubuntu 12.04+, Fedora 21, Debian 8, 64-bit binaries
  • Windows 7+, only 32bit binaries are provided for Windows

Now, fire up your terminal and go into your project’s root folder. Typically, this is where you’re already using node (if you use it). If you put your node modules elsewhere, just change to the proper location. Next, you’ll use the following command to start the installation process:

npm install cypress --save-dev

You may get a brief prompt from Cypress, but otherwise the package should install and plop you back in the terminal. Next, let’s fire Cypress up with the following:

$(npm bin)/cypress open

Firstly, “$(npm bin)” will cause npm to echo the location of the current directory’s binary folder for Node. Secondly, we take that output and concatenate it with the “cypress open” command. On my computer, this expands to “/Users/phatsk/src/WDS/local/playground/app/public/wp-content/node_modules/.bin/cypress open.” You should now see the Cypress screen:

Running Tests

Now that you have Cypress installed and running, you can peruse the samples provided in the “examples” folder. Try clicking one to open a Chrome window that will run the test and give you feedback to each test step. Here you can also click around, expanding tests and using Cypress’s “rewind” feature to see the previous state of the application it’s testing. In this case, the example tests all run against Cypress’s own documentation.

Writing Tests

This is where we start to have fun! Writing tests in Cypress is pretty easy. You just create a JavaScript file in the “cypress/integration/” folder, save it, and it should appear in the main Cypress window after a moment. For this post, I’m going to create a file called “cypress/integration/blog.js” and I’ll add the following content:

describe( 'Testing WebDevStudios.com', function() {
  it( 'Visits the Contact Page', function() {
    cy.visit( 'https://webdevstudios.com' );
    cy.contains( 'Contact Us' ).click();
    cy.url().should( 'include', '/contact' );
  } );
} );

The above script is fairly basic, and a good place to start. Let’s take a look at it, line-by-line:

describe( 'Testing WebDevStudios.com', function() {

This line simply defines our test suite. Here you would give your set of tests a descriptive name.

  it( 'Visits the Contact Page', function() {

Cypress tests are written in a way that kind of makes sense when you read them out loud. For instance, the start of this particular test in our suite describes what we want the test to do—“it Visits the Contact Page.” This line also opens another new function, which will contain our actual test code.

    cy.visit( 'https://webdevstudios.com' );

The “cy.visit” method visits a URL. This is a good time to have a side conversation about testing applications: you should only test applications you own.

The Cypress documentation goes into more detail in Writing Your First Test.” Generally speaking, you won’t be doing much good if you’re trying to test a website or application that you don’t control, and if you’re looking for something to do automated tasks to test for things like load-balancing, there are much better tools than Cypress.

    cy.contains( 'Contact Us' ).click();

The “cy.contains” looks for an element with the text passed to the “contains” method inside of the elements you are selecting against. Since we aren’t chaining the contains command to any selector, it will return the first element on our page that contains the text “Contact Us.” Once we have that element, we want Cypress to “click” the element.

    cy.url().should( 'include', '/contact' );

Finally, we want to ensure that what we clicked took us to the proper place. For that, we assert that the current URL (via “cy.url()”) should include the text “/contact.” The “should()” method is an assertion, and if it passes or fails will be denoted in the Cypress log window.

You can see that Cypress has some pretty nifty features. It has methods for traversing the DOM, finding particular nodes based on text or selectors, and even is aware of when pages are loading so that your tests don’t run too early.

Where to Go Next?

Now that you have a basic idea of how Cypress works, you can start exploring their documentation and hopefully use Cypress to help you better test your applications. I know I’m going to be using it in my own work to help test the applications we create for our clients.

The post Introduction to End-to-End Testing with Cypress.io appeared first on WebDevStudios.

]]>
https://webdevstudios.com/2018/11/13/end-to-end-testing-with-cypress-io/feed/ 0 19366
Database Management https://webdevstudios.com/2018/06/14/database-management/ https://webdevstudios.com/2018/06/14/database-management/#respond Thu, 14 Jun 2018 16:00:31 +0000 https://webdevstudios.com/?p=18684 What Is Database Management? Very simply put, database management is knowing how to access, configure, debug, and manage your database. For some website owners, this isn’t really a concern. Even developers rarely need to poke around with the database, and for many of us, it’s just a piece of software that someone configured once and, as Read More Database Management

The post Database Management appeared first on WebDevStudios.

]]>
What Is Database Management?

Very simply put, database management is knowing how to access, configure, debug, and manage your database. For some website owners, this isn’t really a concern. Even developers rarely need to poke around with the database, and for many of us, it’s just a piece of software that someone configured once and, as many of us like to say, “We’ll never need to touch it again.” This is a typical understanding of database management, especially in the context of WordPress, with the real ins-and-outs of the entire foundation of your website going largely ignored or, at the very least, just not really being thought about.

Now is a good time to stop and explain exactly what a database is. Ready? Wait for it… it’s a base… for your data.

Image result for bad joke dog

Okay, terrible jokes aside, a database is where all of the persistent data for your website live. Depending on how and where your website is located, the database may be on its own server, or it may be sharing the server with your web server. It could be a Relational Database Management System (RDBMS), such as MySQL, Oracle, or MS SQL, to name a few, or it could be a NoSQL database such as CouchDB or Cassandra. This particular article will deal with RDBMS and MySQL/MariaDB in particular since it’s the most widely used RDBMS for WordPress.

Speaking of SQL, what is it? SQL stands for Structured Query Language, and it’s how both humans and programs communicate with the database. Within SQL are all the commands you need to get, modify, create, and delete information. The other good thing about SQL is that it’s a standard adopted by most RDBMSes on the market.

For instance, I can write a simple query that will work in MySQL, PostgreSQL, MS SQL, and Oracle, with little or no tweaks. A “gotcha” here is that all of these RDBMSes implement their own extensions on top of the SQL standards they support, and while most are SQL or ACID compliant, the level of compliance varies between products and even between versions of the same product. RDBMS-specific features include things like Flashback queries in Oracle or tsvector queries in PostgreSQL. Generally, when looking up SQL documentation, it’s best to try and find solutions specific to your RDBMS.

But Why Do I Need to Know This Stuff?

So, why is it important to learn about your database? For starters, we’re in a world where things go wrong all the time. “It’s easy—just one button and you’re done,” or, “It’s a DNS switch, nothing major,” or, “Just push the patch live and see what happens. I’m sure it won’t do any harm.”

I estimate around $10,421 in nickels for every time I’ve heard those phrases and something went wrong.* When things go south, understanding even how to simply access the database can be crucial to getting your site back in working order. Other reasons you may want to really know how things work in your database include:

  • You decide to move to a new hosting provider and you need backups
  • There’s a change that would be tedious through your CMS but trivial in the database
  • Troubleshooting odd behavior or data
  • Monitoring your database when identifying sluggish behavior in your website
  • Making new friends**
  • When you’re developing a new feature and want to understand the relationship of data in your application

There are plenty of other reasons you may want to look around in the database, and once you are familiar with what it does and how it works, you can feel (mostly) confident that you can peruse the raw data without breaking anything. For some tasks myself, I find it much easier to write a quick SQL query that gets the data I need instead of digging through WordPress trying to find it. This is especially true if you work on several projects throughout your day or week and need to do a lot of context switching.

Getting the Right Tools

There are plenty of tools out there to access your database, and I’ll outline a few here:

  • Sequel Pro is pretty much the de facto SQL client for MacOS. It’s free, open-source, and very reliable
  • Navicat is a paid product for accessing various RDBMS servers and has products for Windows, MacOS, and Linux
  • HeidiSQL is a free, open-source SQL client for Windows
  • phpMyAdmin is another open-source SQL administration client with a twist – it runs on your web server instead of being a standalone application
  • The command-line, which most, if not all, SQL servers provide a set of command-line tools to interface with your database. It takes more knowledge of SQL to get up and running, and to be able to do anything, but some people prefer the simplicity of the terminal over sometimes-frilly GUI clients, like the ones above.

Once you have a SQL client installed, you can set up a connection to your SQL server. Depending on where your site is hosted, you may need to contact your site administrator to request this information. If you have a development server (and you should), then pointing your client to the dev server will give you the freedom to poke around without worrying about destroying your site in the process. Which leads us to the next topic…

Backups, Backups, Backups

Any time you are dealing with a database, whether you want to alter a single row or try out some new tricks, take a backup. All of the above programs offer options to export your data to a SQL file. Backups will save you in a crisis, and give you peace of mind while digging into your database. As a rule of thumb for myself, I won’t do any operation on live production data unless I have a backup. Sometimes it’s easy to write a query with two parameters swapped, or missing a clause to limit the query’s scope, and a backup is about the only “undo” button you have in those situations.

Further, your hosting provider should provide a means of taking regular backups. If this isn’t enabled by default, be sure to set it up; if it’s not available, ask your provider for tips on how to connect to your database so that you can take your own backups. If your site is important enough to you, however, and your provider doesn’t provide automatic backups, it may be worth looking to host your site elsewhere.

For WordPress, you can read more about backups on the codex entry for Database Backups.

Cache Me Outside

I’m only briefly going to touch on caching, since it’s a bit technical to set up and beyond the scope of this post, that said: caching is great, especially if you have a site with a large volume of content or even just lots of users.

In the WordPress world, plugins like W3 Total Cache or Rocket Cache can provide caching solutions to improve your site’s performance and take some of the strain off of your database. Another important note about the WordPress database and caching is knowing what functions are cached by WordPress and which cause database hits. Some methods in WordPress force a fresh lookup of data, which can slow down your application. These methods usually have counterparts that are cached and should usually be used instead. An example of one such function is wp_get_object_terms, which suggests using get_the_terms() instead unless you absolutely need fresh data (caching in this sense refers to data cached in the current session, so a fresh page load would still pull uncached data on the first call of wp_get_object_terms). Always be sure to carefully read the documentation to ensure the method you’re using is proper and performant for the task.

WordPress and the Database

Most of what I’ve covered so far is pretty WordPress-agnostic, so now I’m going to touch on the two together. WordPress was written for MySQL, and although there is some support for alternatives, odds are you’re either running MySQL or MariaDB (a fork of MySQL) if you’re running WordPress. MySQL is well-documented, and whilst MariaDB is a fork, it has its own documentation which covers the same ins-and-outs as MySQL, while providing information specific to MariaDB.

You may have configured your database when you first installed WordPress, and you can find out about your database credentials by looking at your project’s “wp-config.php”, where you can find the DB_NAME, DB_USER, DB_HOST, and DB_PASSWORD constants. More reading on this can be found on the WordPress Codex.

Structure

The database is at the core of WordPress. It’s where your posts, tags, users, theme settings, everything is kept. When you start looking at how the database is structured, you can see why WordPress is built on a Relational Database Management System: Posts have IDs, which connect to the wp_postmeta table (on the post_id column), and taxonomy terms are related via the object_id column on the “wp_term_relationships” table. Meanwhile, the comments table is linked back to posts, and even attachments (which are posts as far as the database is concerned) reference their parent post through relational data.

Side note: if you’ve been doing Database Things™ for a while now, you’re probably wondering why WordPress doesn’t really make use of things like foreign key constraints or other key-based relational data. The reason mostly seems to be from the fact that WordPress defaulted to the MyISAM engine for its tables. While offering better performance for things like largely static record reads (what you expect on a blog), it lacked certain features such as Foreign Key Constraints.

For multisite, you’ll notice that most of the tables in standard WordPress are “duplicated” in a sense for the subsites, with prefixes containing the site’s ID. So if your blog “food.coolblogs.com” is site ID 3, its tables will be prefixed with wp_3_. Note that some tables, like wp_users, are shared across all sites, with WordPress using meta keys to differentiate user roles across sites.

Tips for WordPress Database Management

  • Backups – I may have touched on this previously, but it never hurts to reiterate: always take a backup before touching the database
  • Transactions – Typical WordPress installations using MyISAM engines do not support transactions, so be careful when executing SQL queries in WordPress and test your queries on your local machine or a dev instance before running them in production
  • Filters – Practically every part of the queries that get built by WordPress internally for WP_Query can be filtered and adjusted as needed:
    • posts_fields – Filters the SELECT clause of the query
    • posts_search – Filters the search SQL that is used in the WHERE clause of WP_Query
    • posts_search_orderby – Filters the ORDER BY used when ordering search results
    • posts_where – Filters the WHERE clause of the query
    • posts_join – Filters the JOIN clause of the query
  • Serialized data – WordPress makes heavy usage of serialized data to store objects in the database. If you are ever doing large data operations directly on the database, such as replacing one domain with another in a column, it’s important to ensure the integrity of the serialized data afterward. There are several plugins and code snippets on the web that can help you fix things up again. WP Engine also has a blog post explaining serialization and potential gotchas. (Disclaimer: While we work with WP Engine on several projects, I found that blog post organically via Google.)
  • Monitor your performance – Plugins like Query Monitor can give you an under-the-hood look at what WordPress is doing when it works with the database, and can provide feedback that can be used to tweak for performance, reveal bottlenecks, or uncover bugs in custom query implementations. Similarly, you can use command-line tools like mytop to get an overview of the load on your database server.

For further reading on WordPress and the Database, check out the codex page for the Database Description.

Final Thoughts

There’s a lot to learn about WordPress and the database, and if you’re willing, you can get an in-depth understanding of how the pieces fit and better manage your data. There’s a certain feeling of empowerment in understanding the database, and being able to know that you don’t need to panic when something goes wrong makes dealing with fires a lot less stressful.

If like most of us you’re busy and don’t have time to dig into all of this, then the fine folks here at WebDevStudios can help you manage and optimize your database.


* These numbers are best-guess, and I’ve probably actually heard those phrases far more than 2000 times.
** A SQL query walks into a bar, finds two tables and asks, “May I JOIN you?”

The post Database Management appeared first on WebDevStudios.

]]>
https://webdevstudios.com/2018/06/14/database-management/feed/ 0 18684
Is Clever Code OK? https://webdevstudios.com/2016/05/17/is-clever-code-ok/ https://webdevstudios.com/2016/05/17/is-clever-code-ok/#respond Tue, 17 May 2016 15:53:22 +0000 https://webdevstudios.com/?p=12982 “Clever code” is a term that you may have heard before, accompanied by sighs and groans from other developers. Often, people seem to think of clever code as annoying, and perhaps even harmful. In this article, I’m going to give a brief overview of what clever code is, why it’s often avoided, and how it can Read More Is Clever Code OK?

The post Is Clever Code OK? appeared first on WebDevStudios.

]]>
“Clever code” is a term that you may have heard before, accompanied by sighs and groans from other developers. Often, people seem to think of clever code as annoying, and perhaps even harmful. In this article, I’m going to give a brief overview of what clever code is, why it’s often avoided, and how it can be turned into a learning experience.

What is “clever code?”

For most, clever code is code that does not immediately “explain” itself. What that means is that the average developer might see it and have to spend more than a few seconds reading the context around it to understand what it does. Here’s an example in PHP:

$foo = 'bar';
// snip
$value = $foo ?: false;

Considering I’ve been writing PHP for nearly sixteen years, I was bewildered when I first saw this in a co-worker’s code a few weeks ago.

“Pretty nifty, huh?”

You bet! I want to use that in the future, and it is a prime example of clever code–the slang of a programming language.

Opposition to clever code

If you’ve used clever code in the workplace, or in other projects where collaboration is a part of what you do, then you’ve probably run across a decent number of people who don’t like it. Some examples of feedback:

  • “So, why did you do it like this?”
  • “What am I looking at?”
  • “Don’t do that again.”

All very reasonable responses. Clever code is often cited as bringing a disadvantage beyond reading comprehension; it’s also viewed as a source of bugs. Implementing code that is harder to read means it’s more likely that you or a developer working in the same file later are more likely to not read the proper flow of the program. Here’s an example of using PHP’s Bitwise And operator:

// Bitwise And.
$foo = false;
$foo &= false;
$foo &= true;
$foo &= false;

var_dump( $foo ); // int(0)

$foo = false;
$foo &= false;
$foo &= true;

var_dump( $foo ); // int(0)

In the first example, you might expect the outcome of false, or “int(0)”. But the second example is a bit confusing–didn’t that end with setting $foo to true? The Bitwise And operator instead looks at both the left-hand value of “$foo” and the right-hand value when making its assignment; thus, if $foo is false even once, the equation will always look like “$foo = ( 0 * 1 = 0 = false ).” This can be extremely useful, but also incredibly confusing.

Another example of Bitwise confusion comes from the Javascript Bitwise NOT operator:

var a = ["f", "o", "o", "b", "a", "r" ];

if ( a.indexOf( "g" ) > -1 ) {
    console.log( "Typical style" );
}

if ( !!~a.indexOf( "g" ) ) {
    console.log( "Clever style" );
}

Again, we can see that the “tilde” operator, coupled with a double negative “!!”, creates clean code that won’t make sense to the average programmer.

How to be smart and clever

This all leads to what I’d like programmers to start doing when considering clever code: create a learning environment for other developers. I’ve seen clever solutions criticized on StackOverflow, and a particular question about it on the Programmer’s StackExchange asking for advice on how to avoid writing clever code in the first place. 

This, to me, is a great example of how programmers see clever code: it’s a party trick; it’s dangerous; it is to be avoided by “serious” programmers.

On the other hand, I think we can start to turn clever code into a learning experience. Once you recognize clever code, you can start to document it when you use it so others on the project know what you’re doing:

function check_user( $can_go_on ) {
    /**
     * NB, Clever: Using PHP's bitwise And operator.
     * See: http://php.net/manual/en/language.operators.bitwise.php
     */
    if ( ! current_user_can( 'manage_network' ) ) {
        $can_go_on &= false;
    }

    return $can_go_on;
}

function check_screen( $can_go_on ) {
    $screen = get_current_screen();

    if ( ! $screen || 'post' !== $screen->base ) {
        $can_go_on &= false;
    }

    return $can_go_on;
}

add_filter( 'can_we_continue', 'check_user' );
add_filter( 'can_we_continue', 'check_screen' );

$can_go_on = apply_filters( "can_we_continue", true );

In the above example, the ‘check_user’ function is documented to give a clear and distinct “Hey! I’m doing something weird here,” as opposed to the second method ‘check_screen’ which quietly uses the Bitwise And without any discussion. Most any programmer would be forgiven for missing it or thinking it’s a typo, and a scrutinizing lead would almost certainly see it and think “Great–now I have to change this and test everything this filter touches.”

A real world example looks like this:

/**
 * CLEVER CODE ALERT. This shorthand ternary accepts the tested value as the value returned if
 * true, otherwise the else value. NB this does not work in reverse (i.e. $a = $b ? 'value' :; ).
 */
$blog_id = $blog_id ?: get_current_blog_id();

Here’s that nifty shorthand ternary again! This saves some characters and looks pretty neat, but there’s a pretty hefty comment above it to explain what’s going on. The comment alone negates the time saved in not writing out the whole ternary, but for me the point of code like this, and the associated documentation, is to teach and inform others.

As programmers working in an increasingly collaborative world, we should be making strides in documentation–not only to guide other developers through the big ins and outs, but also to illuminate the many tricks and secrets that the language holds.

Happy coding!

The post Is Clever Code OK? appeared first on WebDevStudios.

]]>
https://webdevstudios.com/2016/05/17/is-clever-code-ok/feed/ 0 12982
Writing Clean(er) JavaScript https://webdevstudios.com/2015/10/27/writing-cleaner-javascript/ https://webdevstudios.com/2015/10/27/writing-cleaner-javascript/#respond Tue, 27 Oct 2015 18:15:59 +0000 http://webdevstudios.com/?p=11923 JavaScript, like many programming languages, has some great ways to compartmentalize and structure code to make it more maintainable, more readable, and more reliable. This post will cover two things that can help developers to organize their code: namespacing and singletons. Namespacing While JavaScript has no formal “namespaces,” the ability to have pretty much anything be a Read More Writing Clean(er) JavaScript

The post Writing Clean(er) JavaScript appeared first on WebDevStudios.

]]>
JavaScript, like many programming languages, has some great ways to compartmentalize and structure code to make it more maintainable, more readable, and more reliable. This post will cover two things that can help developers to organize their code: namespacing and singletons.

Namespacing

While JavaScript has no formal “namespaces,” the ability to have pretty much anything be a member of any object allows developers to emulate them somewhat effectively. You could consider the “window” to be its own namespace, containing what we often refer to as “global” variables. In this sense, everything created in the global scope is actually under the “window” namespace:

var foo = 'bar';

console.log( window.foo ); // bar

window.foo = 'baz';

console.log( foo ); // baz

Developers are often discouraged from polluting the window object with variables; this creates several issues that aren’t necessarily Big Problems, but can create headaches and difficult debugging situations in the future.

var i = 10;

do_something();

for ( i > 0; i--; ) {
    console.log( i );
}

function do_something() {
    for( i = 0; i < 4; i++ ) {
        console.log( i );
    }
}

The output above, with commas separating for each call to “console.log”, is:

0, 1, 2, 3, 3, 2, 1, 0

Most programmers familiar with JavaScript and scoping will immediately see why the code above is problematic – the “i” variable in our function “do_something” wasn’t bound to the function’s scope (no use of the “var” keyword). When we called our function, the global “window.i” was accessed and overwritten. Working in the global scope also causes issues with keeping code organized:

function trim_space_from_form_input() {}
function trim_space_from_url_input() {}
function validate_input_from_form() {}
function validate_input_from_url() {}

In programming, it’s not uncommon to have several functions that do similar tasks but somewhat differently from one another. In a global space, it becomes increasingly difficult to quickly find and parse the available functions. This can lead to duplicating work, confusing function names, and uncertainty for any developer who may come in to work after you. So, what’s a JavaScript namespace? Like just about everything else in JavaScript, you can use an object for a namespace:

var WDS = {};

WDS.forms = {};
WDS.url = {};

WDS.forms.trim_space = function() {};
WDS.forms.validate_input = function() {};
WDS.url.trim_space = function() {};
WDS.url.validate_input = function() {};

// Or, alternatively

var WDS = {
    forms: {
        trim_space: function() {},
        validate_input: function() {}
    },
    url: {
        trim_space: function() {},
        validate_input: function() {}
    }
};

While those two methods don’t appear cleaner and indeed are a little more “wordy” than the original, what they do provide is cleanliness in the form of keeping relevant code separated from the rest of the environment. Instead of hunting through source files, the developer can inspect the “WDS” object and see what properties it has, and add his or her own properties to extend it.

A simple namespacing function can help you to quickly create objects that can be used to organize your code’s functionality:

/**
 * Accepts a string to create a "namespace"
 *
 * @param String ns The namespace to create - works recusively by separating children with dot "."
 * @param Object global[=window] Optional global object to create the namespace in, defaults to window
 *
 * @return Object The furthest point in the namespace
 */
function create_ns( ns, global ) {
  global = global || window;

  ns = ns.split( '.' ); // split the namespace into components

  for ( var key in ns ) {
    if ( ! ns.hasOwnProperty( key ) ) {
      continue;
    }

    key = ns[ key ]; // Grab the "text" key

    // Create the property "key" within the global object
    if ( ! global.hasOwnProperty( key ) ) {
      global[ key ] = {};
    }

    global = global[ key ]; // reassign global so that we can continue to add sub-properties
  }

  return global;
}

/**
 * Creates the window.WDS object if it doesn't exist, and creates the forms property on window.WDS if that
 * doesn't exist
 */
create_ns( 'WDS.forms' );

// Now, WDS.forms is available to use however we want, for instance adding some methods
WDS.forms.CreatForm = function() {};
WDS.forms.ProcessForm = function() {};
WDS.forms.POST_TYPE = 'POST';

/**
 * In this example, you could use "this" as the global so that the newly created object has a prepared internal structure
 */
function my_thing() {
  create_ns( 'utilities.string_stuff', this );
}

var thing = new my_thing();
thing.utilities.string_stuff.Compare = function( a, b ) {
  return a == b;
};

Singletons

Another design pattern that helps keep JavaScript clean, both in terms of tidyness and overhead, is the singleton pattern.

Often in programming, we are used to instantiating classes over and over again, but we also want to have classes that we only instatiate once and use them over and over. These are singletons, a good example of a singleton class would be a factory to generate new objects, or a utility class to deal with templating.

create_ns( 'WDS.util' );
WDS.util.TemplateManager = function() {
    if ( WDS.util.TemplateManager.prototype._singletonInstance ) {
        return WDS.util.TemplateManager.prototype._singletonInstance;
    }

    // "private" variables 
    var templates = {};
    var tpl_regex = new RegExp();

    WDS.util.TemplateManager.prototype._singletonInstance = this;

    this.render = function ( id, variables ) {
        if ( ! this.get_tpl( id ) ) {
            throw "Could not find template " + id;
        }

        return apply_data( this.get_tpl( id ), variables );
    };

    this.add_tpl = function( id, template ) {
        templates[ id ] = template;
    };

    this.get_tpl = function( id ) {
        return templates[ id ] || false;
    };

    function apply_data( template, variables ) {
        for ( var key in variables ) {
            if ( ! variables.hasOwnProperty( key ) ) {
                continue;
            }

            tpl_regex.compile( '{' + key + '}', 'g' );
            template = template.replace( tpl_regex, variables[ key ] );
        }

        return template;
    }
};

// Now, no matter how many times we contruct this object...
var MyTemplateUtility = new WDS.util.TemplateManager();
MyTemplateUtility.add_tpl( 'my_template', '<div id="{div_id}">{div_content}</div>' );

var SomeOtherTemplateUtility = new WDS.util.TemplateManager();
console.log( SomeOtherTemplateUtility.get_tpl( 'my_template' ) ); // <div id="{div_id}">{div_content}</div>

// we are still acccessing the same instance
console.log( MyTemplateUtility === SomeOtherTemplateUtility ); // true

Using the singleton pattern, we can confidently instatiate the TemplateManager class anywhere in our code and be sure that we’re always dealing with the same instance as the first time we used it: all templates loaded to the utility will be accessible to the object no matter when or where it’s called upon. This also reduces code overhead in the browser, as we aren’t needlessly polluting the environment with multiple objects that all do the same thing.

Conclusion

While JavaScript, and any language really, can be a tangled ball o’ mess, we as developers can do our part to write more maintainable, organizable, and reusable code. Namespaces help keep our code organized into sensible chunks, while singletons create easily reusable classes that can persist their state during the life of a request.

Happy coding!

The post Writing Clean(er) JavaScript appeared first on WebDevStudios.

]]>
https://webdevstudios.com/2015/10/27/writing-cleaner-javascript/feed/ 0 11923
The Future of JavaScript: ECMAScript 6 and You https://webdevstudios.com/2015/06/30/the-future-of-javascript/ https://webdevstudios.com/2015/06/30/the-future-of-javascript/#comments Tue, 30 Jun 2015 17:50:16 +0000 http://webdevstudios.com/?p=11376 Today, JavaScript fills every aspect of our online lives: it checks your e-mail in the background, it guides your online shopping cart, and it even autosaves your blog post as you write. From the client to the server, JavaScript is everywhere. Sometimes it’s hard to remember that this wasn’t always the case. When I started writing basic Read More The Future of JavaScript: ECMAScript 6 and You

The post The Future of JavaScript: ECMAScript 6 and You appeared first on WebDevStudios.

]]>
Today, JavaScript fills every aspect of our online lives: it checks your e-mail in the background, it guides your online shopping cart, and it even autosaves your blog post as you write. From the client to the server, JavaScript is everywhere. Sometimes it’s hard to remember that this wasn’t always the case.

When I started writing basic web pages in the late 90’s, “DHTML” was the acronym describing the use of JavaScript, HTML, and CSS; the “D” stood for “Dynamic.” DHTML sites were heavy and sluggish, yet they showcased the power of JavaScript (or JScript, depending on who you asked). They also served as a reminder of why many developers shied away from JavaScript at the time: it was resource-intensive, and implementations varied from browser to browser. At the time, I only knew a handful of people who did any kind of web development–we were, after all, more concerned with the issues of how much AP courses “sucked” and whether or not we could get tickets to see Blink 182. For us, the consensus was that JavaScript was for show, and any website could do what it needed to do without it.

JavaScript has now made a name for itself as the go-to for interactive sites. Gone are the days of full-page Flash applications, Shockwave Player, and Java as a general “necessity” for the web. JavaScript has even found it’s way onto the server with projects such as Node.js. Automation of screenshots, converting web pages to PDF, or headless testing can all be achieved from the command link using PhantomJS, a headless implementation of the WebKit engine. On the wider web, JavaScript gives us the little spinner that eventually leads to a table of search results populating without a page reload, or dragging-and-dropping an image to upload it to Imgur. Even some of the apps on the smartphones in pockets around the world use JavaScript. It’s no longer just for hobbyists or experimentation – knowing JavaScript is a part of the job.

Which brings us to ECMAScript 6, or ES6. JavaScript is an implementation of ECMAScript, which also covers languages such as ActionScript, JScript, QtScript, and many others. ES6, codenamed “Harmony,” has been in the works since 2008 and periodic drafts have been published since 2011. This month, June 2015, ECMAScript 6 was formally announced and released and includes a lot of new and interesting tidbits for developers of the modern web.

Below I hope to cover some of the new features, but by no means all of them, as that would be far beyond the scope of this post. For more information, you can check out the full specification PDF to get a look at all of the stuff coming to a browser near you.

Author’s note: the following will include some code examples – some modern browsers may still not recognize certain keywords or agree with their use. For instance, Chrome requires “use strict” to make use of the “let” keyword.

Constants

A simple idea in many languages, Constants have been absent in JavaScript until now. In programming, a constant is similar to a variable, in that you assign a value to an identifier, but differs in that it can never be changed throughout execution of the program. An example in PHP:

define('APPLICATION_VERSION', '1.2.0.4332');
echo APPLICATION_VERSION; // 1.2.0.4332
define('APPLICATION_VERSION', '1.3'); 
// Notice: Constant APPLICATION_VERSION already defined
echo APPLICATION_VERSION; // 1.2.0.4332

The constant APPLICATION_VERSION is defined and can never be altered, and PHP will let you know that if you try (and your error reporting is on). Attempts to redefine the constant will fail, and the original value will hold true. In Javascript, this was previously achieved by the clunky mechanism of defining a new Object property–this was only available in ES5, and only in the global scope. With ES6, things get a lot easier:

const APPLICATION_VERSION = '1.2.0.4332';
console.log(APPLICATION_VERSION); // '1.2.0.4332'
APPLICATION_VERSION = '1.3.0'; // "1.3.0"
console.log(APPLICATION_VERSION); // '1.2.0.4332'
// Notice that the Chrome console evaluated the assignment
// on line 3, however the value didn't change

If we try to actually redefine the constant we get an error:

JavaScript constant redefinition

 

While a simple addition, the introduction of constants to JavaScript shows that the language is maturing in a way that will be welcome by many programmers.

How about something a little more interesting?

Default Parameter Values

If you have programmed in JavaScript, you’ve dealt with all of the ways in which default parameters can be mimicked in the language:

// The "if" way
function say_hi(iterations, greeting, name) {
    if( iterations === undefined ) {
        iterations = 5;
    }

    if( greeting === undefined ) {
        greeting = 'Hello';
    }

    if( name === undefined ) {
        name = 'World';
    }

    for ( var i = 0; i < iterations; i++ ) {
        console.log( greeting + ', ' + name );
    }
}

// The "||" way
function say_hi(iterations, greeting, name) {
    iterations = iterations || 5;
    greeting = greeting || 'Hello';
    name = name || 'World';

    for ( var i = 0; i < iterations; i++ ) {
        console.log( greeting + ', ' + name );
    }
}

// The jQuery "extend" way
function say_hi(args) {
    var params = {};
    var defaults = {
        iterations: 5,
        greeting: 'Hello',
        name: 'World'
    };
    
    jQuery.extend(params, defaults, args);

    for ( var i = 0; i < params.iterations; i++ ) {
        console.log( params.greeting + ', ' + params.name );
    }
}

Above we have several methods to handle “default parameters,” none of which are really ideal. The first method is clunky, the second method is cleaner but not necessarily self-explanatory (especially to novice programmers), and the third method uses jQuery’s “extend” method–this is a great way to define a default set of options in an arguments object, but this also obfuscates the intent of the function – you wouldn’t know it took those arguments just by looking at the method signature, and seeing it in use without one of the object properties defined would leave you oblivious to the fact that you could pass that property without reading the documentation or diving into the source.

ES6 introduces default variables in a way that should be familiar to most programmers. The new method is clean and readable:

function say_hi( iterations = 5, greeting = 'Hello', name = 'World' ) {
    for ( var i = 0; i < iterations; i++ ) {
        console.log( greeting + ', ' + name );
    }
}

At the time of writing, this only works in Firefox (versions 15 and on support basic defaults, while versions 26 and 41 introduce more complex usage). Chrome has an open support ticket to implement this feature in the V8 JavaScript engine, and any browser working towards ES6 should be following suit.

String Interpolation

Something I’ve done for a long time, templating with strings, usually requires custom functionality, regular expressions, and somewhat clunky code. The separation of template and data can hide how things tie together. Here’s an example done with an Ext.JS-like templating function:

function tpl( data, template ) {
    var r = new RegExp();

    for ( var key in data ) {
        if ( ! data.hasOwnProperty( key ) ) {
            continue;
        }

        r.compile( '{' + key + '}', 'g' );
        template = template.replace( r, data[ key  ] );
    }

    return template;
}

var myTplData = {
    name: 'John Smith',
    address: '4124 Rasperry Lane',
    city: 'Heartford',
    state: 'CT'
};

var myTpl = [
    '<div>',
        '<strong>Name: </strong> {name} <br/>',
        '<strong>Street Address: </strong> {address} <br/>',
        '<strong>City, State: </strong> {city}, {state} <br/>',
    '</div>'
].join("\n");

console.log( tpl( myTplData, myTpl ) );

/**
<div>
<strong>Name: </strong> John Smith <br/>
<strong>Street Address: </strong> 4124 Rasperry Lane <br/>
<strong>City, State: </strong> Heartford, CT <br/>
</div>
 */

The above code isn’t exactly great, and rather simple. When you look at Ext.JS’s XTempalte, you see just how much complexity gets added to what sounds like a straightforward concept. Other libraries provide their own methods of binding data to templates, but ES6 can at least begin to replace some of this functionality with an easier approach:

var myTplData = {
    name: 'John Smith',
    address: '4124 Rasperry Lane',
    city: 'Heartford',
    state: 'CT'
};

var myTpl = `
    <div>
        <strong>Name: </strong> ${myTplData.name} <br/>,
        <strong>Street Address: </strong> ${myTplData.address} <br/>,
        <strong>City, State: </strong> ${myTplData.city}, ${myTplData.state} <br/>
    </div>`;

console.log( myTpl );

/**
<div>
    <strong>Name: </strong> John Smith <br/>,
    <strong>Street Address: </strong> 4124 Rasperry Lane <br/>,
    <strong>City, State: </strong> Heartford, CT <br/>
</div>
 */

This completely removes the need for Regular Expressions, and carries a syntax somewhat familiar to those who use PHP and other languages. Integration of variables and strings has been long overdue for JavaScript, so it’s good to see ES6 finally make a change.

And More…

These are just a few of the myriad features coming in ECMAScript 6. While some of these exist in current browser implementations (notably Chrome and Firefox), we likely won’t see the full specification implemented for a few months, and adoption across the board will likely take much longer. That doesn’t mean there aren’t more things to look into and get excited about, such as MapsClassesIterators and Generators, and more.

The post The Future of JavaScript: ECMAScript 6 and You appeared first on WebDevStudios.

]]>
https://webdevstudios.com/2015/06/30/the-future-of-javascript/feed/ 1 11376