Half-Elf on Tech

Thoughts From a Professional Lesbian

Tag: wordpress

  • Slow Site Troubleshooting: Database Edition

    Slow Site Troubleshooting: Database Edition

    So your WordPress is slow and you’ve already done the needful. You’ve checked your plugins and themes, you’ve put caching in place, you’ve checked for hacks, but it’s still slow, especially on the back end of WordPress?

    It may be your database.

    More specifically it may be your wp_options table. When your options table gets very, very large, it gets very, very slow. WordPress regularly queries that when you’re logged in, and it’s not indexed. DB indexes are used to locate data fast, without searching every row in the tables. This sounds sensible in many ways, but we don’t

    Indexes are used to quickly locate data without having to search every row in a database table every time a database table is accessed. Indexes can be created using one or more columns of a database table, providing the basis for both rapid random lookups and efficient access of ordered records. We don’t use ’em in the options table for a variety of reasons, but mostly that it slows things down.

    So in lieu of making indexes on your own, what can and should you do to debug things?

    Optimize Your Database

    Got WP-CLI?

    wp db optimize
    

    Otherwise you can use phpMyAdmin to check tables with overhead and clean ’em up. I don’t use a plugin, I think asking WP to optimize itself is a little weird, but you certainly can. The point here is to keep it clean.

    Cache that Database!

    Caching makes things better. Right? Kind of right. Mostly right. I use memcacheD (which I often typo as memecached) and that plus an object-cache.php file can cache your DB calls so they’re faster, which is great. Unless your wp_optimize table is too big.

    Your cache has two major issues. First, there’s going to be data you don’t want to cache (like private, sensitive information), but also when your cache is too big, or it’s trying to save data bigger than it is, it can make things slower by trying to cache, crashing, and repeating that over and over. That gets worse when we talk about the temp data generated by _transient entries in your database.

    Check The Size

    Your options table really shouldn’t be large. My biggest, busiest, site is only using 142K. It’s a site that’s old (8+ years now), it’s had many iterations and themes and plugins. You’d think it would be filthy with leftover code, because we all know plugins don’t always clean up. Nope. I did rebuild the DB once, in 2009, when I rebuilt the entire site from scratch, but that was 5 years ago and a lot has changed since then with plugins and themes. The next biggest site, a Multisite Network, has a wp_options of 100k. The biggest I’ve had is one of 500kb and that’s on a test site where I install and delete plugins daily.

    You get the point I trust. These things should be small. At most, I’m going to have a lot of _transient entries. But that’s actually issue here.

    Clean The Transients

    There’s a story here about why WordPress doesn’t really clean your transients. Why? Well as the name implies, transient data is meant to be transient. It should be temporary data, saved and used briefly, and then it should go away. A lot of developers, as it happens, were storing it for long term caches. Like checking when the last upgrade ran, or when a cron kicked off. So while for one, glorious, month we did nuke them all on upgrade, now we only delete expired transients, which doesn’t help as much as it could. As Nacin said:

    This leaves much to be desired, but we don’t want a core update to be blamed for breaking a site that incorrectly assumes transients aren’t transient.

    Basically people doing things wrong in a way we couldn’t adjust for.

    There are plugins like Delete Expired Transients and Transient Cleaner (which has the cutest header image). Those can be used to clean out your old transients.

    If you want to go whole hog, there’s a command to clean the whole thing out with SQL:

    DELETE FROM `wp_options` WHERE `option_name` LIKE ('%\_transient\_%')
    

    Of course you want to run a db optimize afterwards to actually flush out the rows.

    As always WP-CLI has features like wp transient delete-expired and wp transient delete-all.

    What if that doesn’t help?

    Then you should check the Database to see exactly what the biggest value is. In this case, I ran wp db cli to leap into the database and then this:

    mysql> SELECT option_name , length (option_value) AS blah FROM wp_options ORDER BY blah DESC LIMIT 5;
    +--------------------------------------------------+----------+
    | option_name                                      | blah     |
    +--------------------------------------------------+----------+
    | cron                                             | 12194468 |
    | _transient_feed_d117b5738fbd35bd8c0391cda1f2b5d9 |   223838 |
    | _transient_feed_ac0b00fe65abe10e0c5b588f3ed8c7ca |    98184 |
    | _transient_is_cached_instagram_images_self       |    97315 |
    | mytheme_storage                                  |    18354 |
    +--------------------------------------------------+----------+
    10 rows in set (0.02 sec)
    

    CRON is 12 megs. That would be the problem. Of course the only way I know of to fix that would be to totally trash cron and let it start over.

    Is That It?

    When you see a ginormous wp_options table, what do you do?

  • Mailbag: Debugging the Dread “No Permissions”

    Mailbag: Debugging the Dread “No Permissions”

    Sometimes customers hunt me up here. That’s okay. I’d rather you opened a ticket since I like to eat, sleep, and hang out with my wife, but in this case they also had an interesting problem.

    When I log in, I get “You do not have sufficient permissions to access this page.”

    I found the support ticket and solved it, and then I mailed the DreamPress Ninja’s with this methodology. It relies on wp-cli, so bear with me.

    The first thing to do is check the user list:

    user@server:~/example.com$ wp user list
    +----+-----------------+--------------------------------+-----------------------------+---------------------+---------------+
    | ID | user_login      | display_name                   | user_email                  | user_registered     | roles         |
    +----+-----------------+--------------------------------+-----------------------------+---------------------+---------------+
    | 2  | bobby           | Bobby Done Nightly             | bobby@example.com           | 2014-02-12 17:44:28 | administrator |
    | 3  | darren          | Darren Done Rightly            | darren@example.com          | 2014-09-29 17:49:11 | contributor   |
    | 4  | ethan           | Ethan Done Wrongly             | ethan@example.com           | 2014-10-27 21:01:07 | subscriber    |
    | 5  | jimmybear       | Jimmy Eaten By A Bear          | jimmy@example.com           | 2013-12-16 14:45:18 | author        |
    | 1  | iamempty        | Admin Account                  | admin@example.com           | 2015-03-05 01:30:09 |               |
    | 6  | sonnyboy        | Sonny Boyd                     | sonny@example.com           | 2014-10-27 22:13:08 | contributor   |
    +----+-----------------+--------------------------------+-----------------------------+---------------------+---------------+
    

    Notice how imaginet has NO role? That’s the problem. So let’s give it a role!

    user@server:~/example.com$ wp user add-role 1 administrator
    Success: Added 'administrator' role for imaginet (1).
    

    Check again and all is happy!

    user@server:~/example.com$ wp user list
    +----+-----------------+--------------------------------+-----------------------------+---------------------+---------------+
    | ID | user_login      | display_name                   | user_email                  | user_registered     | roles         |
    +----+-----------------+--------------------------------+-----------------------------+---------------------+---------------+
    | 2  | bobby           | Bobby Done Nightly             | bobby@example.com           | 2014-02-12 17:44:28 | administrator |
    | 3  | darren          | Darren Done Rightly            | darren@example.com          | 2014-09-29 17:49:11 | contributor   |
    | 4  | ethan           | Ethan Done Wrongly             | ethan@example.com           | 2014-10-27 21:01:07 | subscriber    |
    | 5  | jimmybear       | Jimmy Eaten By A Bear          | jimmy@example.com           | 2013-12-16 14:45:18 | author        |
    | 1  | iamempty        | Admin Account                  | admin@example.com           | 2015-03-05 01:30:09 | administrator |
    | 6  | sonnyboy        | Sonny Boyd                     | sonny@example.com           | 2014-10-27 22:13:08 | contributor   |
    +----+-----------------+--------------------------------+-----------------------------+---------------------+---------------+
    

    If the roles had be totally empty, it’s a case where the database is looking for the ‘wrong’ table prefix and that’s a little messier. There, you’ll want to grab the table prefix from the wp-config.php file:

    $table_prefix  = 'wp_hsy671e_';
    

    Then go into the database and look at wp_hsy671e_options for a field called wp_hsy671e_user_roles – if you don’t see one, that’s the problem. Check for one named wp_user_roles and rename it.

    If you DO see the right user_roles, then the problem is all the users are pointing to the wrong table. You can just run wp search-replace wp_user_roles wp_hsy671e_user_roles to force it back.

  • I Hate Your Framework

    I Hate Your Framework

    The plugin itself was one PHP file and three JS files.

    The framework was over two megs.

    The plugin added in a new setting to select which one of the three javascript files should be called.

    The framework ‘made it pretty.’

    I’m right up there telling people that the WordPress Settings API is a giant bag of wet hair. It’s confusing, it’s cryptic, it doesn’t always play well with everything, and sometimes it makes you feel like the point is to make us have decisions, not options, for our plugins. But I don’t think plugin frameworks are the answer. At least not the way most people seem to be going about them.

    When I say frameworks, I don’t mean the libraries like the AWSSDK for PHP framework that you package up into your plugin and do a proper check for a function, calling yours if the the library isn’t there. No, I mean the plugins that are totally separate plugins but are meant to be called by yours in order to make development easier and more consistent.

    That’s what I hate.

    I love the idea of these frameworks, actually. I think that a boilerplate plugin, similar to _underscores, where I can put in my plugin name, my information, and press a button to have the basic plugin files generated for me is brilliant! But I think most of the libraries out there are doing it in a way that will annoy and upset most people.

    The problem is less the framework and more the people using them as a ‘quick fix’ without properly thinking about what they want to do.

    They’re Too Large

    In the case of this plugin, one file with three settings could just be done with two functions (maybe three) and instead he’s made a download half the size of WordPress core. The zip is large, it makes things take just a little bit longer for people on slow servers to download and upgrade, and the larger you get, the worse you are for the really small shared hosts. I know a lot of people argue with me about this, but remember than a high number of hosts still default you to allow 7M in PHP upload size. That means when your plugin becomes the 30 meg behemoth with all your dev files, you’ve made things pretty bad for some users. But even when you’ve only made your plugin 2 or 3 megs, why would you do that when you have one file of actual code?

    The logic escapes me.

    They’ve Got Too Many Files

    Not the same thing as too large! There are hundreds of files in a framework, and if you’re using only 4, that means you have 96+ files to review for security. You just increased your workload for not enough value. Which is really a major part of my next issue. The point here is you, the developer, are responsible for every single file in that framework. You are expected to know everything about it, where it installs, what it uses, why it uses it, and when to upgrade. This is a pain. It’s a chore. And it’s your job now.

    You Don’t Know How to WordPress

    This is also why I don’t like the idea of making Multisite too much easier. The further you take a developer from writing this code, the further they get from understanding how it all comes together and the harder it is for them to debug their own plugins. If you’re developing a plugin you plan to share with other people, even a teeny tiny one, you need to understand what you’re doing. You need to learn about the way the code interacts with the CMS tool, you need to understand why some things are secure and others are not.

    You Use the Frameworks Wrong

    I said before, I love the idea. And I do. They’re a brilliant idea and, when done right, work perfectly. The problem with them is, a bit, a problem with WordPress, which is we really don’t have a way to handle children plugins. You see, the best thing for a true framework plugin would be to have it be a separate plugin. But without plugin dependency support in core or the directory, it becomes another level of hassle for users.

    For example… if you have the plugin as a separate plugin, these are the issues we’ve see for end-users (not developers):

    • Not recognizing the framework plugin, and thus deleting it (causing the plugin(s) to break)
    • Not recognizing the framework plugin and thinking they’ve been hacked
    • Updating the framework plugin separately from the dependent plugins, possibly leading to breakage
    • Updating a dependent plugin without updating the framework, possibly leading to breakage
    • Different plugins requiring different versions of the framework

    And bearing in mind that the framework and plugin developers are different people, that’s another level of coordination/compatibility issues. Frameworks and libraries should be packaged with each plugin (hopefully in a way that doesn’t conflict with other plugins using the framework or libraries). At least until core supports plugin dependencies.

    But I still think that’s wrong.

    I still think the best framework plugin isn’t a plugin at all, it’s a tool to help you design and build a plugin via your editor of choice. Or maybe a Grunt Script that lets you build it out based on parameters. Time spend making a framework for making the plugin ‘interface’ better would be better spent making the Settings API better.

  • Mailbag: Learning Resources

    Mailbag: Learning Resources

    Ann asked about books:

    [..] if you’re open to throwing a few key book recommendations – sites – blogs – whatever resources that you use/have used and particularly liked – I would be grateful. Essentially – I love your blog and am always looking to improve my WP developer skills. I want to get better. I want to be really really good. So I ask the greats if there’s something in particular that they think I should read – out of the huge sea of articles/books/blogs/etc out there. Something that they’ve singled out and thought was really worth paying attention to. And then I read it! [..]

    She got an email reply right away, but here’s for everyone else.

    The best advice I have is to pick something you like (or that drives you absolutely up the wall) and poke at it.

    I got started and good because I really, really, really, wanted to do something that (at the time) WP didn’t do. After banging my head a lot, I started googling and trying to figure out what was there to use. I looked at a lot of code that was ALMOST what I wanted. And I broke my test site. A looooooooot.

    The biggest problem is we all learn differently. I learn by doing, so for me the act of writing BAD code helps me understand it better. I hate videos.

    But do I have a specific resource for learning? Sometimes I do. The majority of my ‘research’ remains search engines and constantly refining parameters, or trying to remember the name of the one thing with the thing. The problem is that I’m very haptic, I learn by doing things, so for me it’s way easier to take the examples and break them than anything else.

  • Mailbag: What Code Makes You Sigh?

    Mailbag: What Code Makes You Sigh?

    When I was talking about ThemeForest, I mentioned we had code on WordPress.org that made me sigh. Or cry depending on the day.

    Here it is:

    if (!defined('WP_CONTENT_URL')) define('WP_CONTENT_URL', get_option('siteurl').'/wp-content');
    if (!defined('WP_CONTENT_DIR')) define('WP_CONTENT_DIR', ABSPATH.'wp-content');
    if (!defined('WP_PLUGIN_URL')) define('WP_PLUGIN_URL', WP_CONTENT_URL.'/plugins');
    if (!defined('WP_PLUGIN_DIR')) define('WP_PLUGIN_DIR', WP_CONTENT_DIR.'/plugins');
    

    Why do I sigh?

    It’s not needed.

    You can use functions to determine those directories and while I’m sure someone’s thinking “But WP_PLUGIN_DIR is shorter than plugins_url()!” it’s not.

    That code block above was used so that one line of code could exist.

    include(WP_PLUGIN_DIR.'/PLUGINNAME/settings.php');

    Those four lines, plus the include, could be replaced with this:

    include( plugins_url( 'settings.php' , __FILE__ ) );

    So yes, I sigh. Because with just a little work, you could see that there’s a more efficient way to make your plugin smaller.

  • Stop Using Copy Protection

    Stop Using Copy Protection

    I’ve seen a million features out there to ‘prevent people from stealing your content.’ The idea is that by preventing people from (easily) copying your work, you stop them from stealing it and profiting off your efforts. You may even think that you’re saving your images from being stolen. In general, they use javascript to prevent things like right-click, view source, copying text, and disabling keyboard short cuts. In general, they suck and here’s why.

    User Experience

    Anyone who uses a screenreader or an alternative mouse tool now, officially, hates you. You’ve made your site look like absolute crap. Some screen readers can no longer read your content at all. Also not everything handles javascript very well (which is by far the ‘most popular’ way to block out content) and that makes for a pretty lousy experience for your visitors.

    Support

    If you have a problem with your website and ask the world at large for help, they will take one look and hate you. No one can easily help you with your CSS or your layouts or your design now, because you’re protecting content. When customers ask for help, the first thing I do is turn those plugins off so I can use my normal debugging methods and not worry about cruft interference.

    It Doesn’t Work

    If you disable right-click, you make it harder for me to bring up Chrome’s dev tools, but not impossible. You can’t make it impossible. This is, in part, because there are so many different browsers to account for, but also because developers really don’t want you to be able to kill dev tools. We need them to fix the web, and if I were to leave the dev tools open and then visit your site I would be able to have it open on your site.

    Once I have dev tools open, I can view the resources loaded by your page. Take Instagram, who doesn’t let you right-click on an image to download. I can instead right-click, chose ‘Inspect Element’ and I get this:

    element.style {
        background-image: url(http://photos-g.ak.instagram.com/hphotos-ak-xaf1/t51.2885-11/10912600_6619567248918_1818171895_n.jpg);
    }
    

    Guess what I can do now? Load that URL in another window, download, done. If that’s not available, I’ll go over to the Resources tab, open up the Instagram folder, then Images, and find the image I want. Again, done.

    There’s Only One Way

    There is but one foolproof way to prevent your content from being stolen: Don’t publish it.

    But of course no one wants to hear that. So what’s the other way? Well give up on not having your words stolen. Even if you make it difficult, people will get at it. People type up books and scripts today, they’ll do it for your website if they’re properly motivated. Images, on the other hand, are a different issue. If you’re a photographer, don’t put your full-sized images online unless you’re selling them. And if you are selling photographs, put them on a cloud host like Amazon. Large files and PHP aren’t the best of friends anyway. Your website, unless it’s a store, doesn’t need the 10meg image file.

    As much as it pains me to say it, DRM is also a solution. So is watermarking your images. The way people like Getty protect their images is to lock it down to purchased users only. You can (fairly easily) download the smaller, sample images, but the awesome big ones are locked down.

    But that’s how you protect your content. Not with those plugins.