Ember: Using queryParams to distinguish “editing a record” from “making a new record” on a route

This guide uses Ember 1.13


The concept is simple and familiar: you have a page (“route”) in your Ember app that you want to use to either enter new data or modify existing data on the same record.

Example: your user is presented with a blank form to enter their shipping address.  The user enters their info and submits it (thus creating a new record). When your user goes to edit their saved shipping address, that same form is populated with their existing shipping information (loading a record). The user edits, saves, and the updated record is persisted.

One form, two behaviors (new and edit). 

This, like many things in Ember, was surprisingly painful to get working. I found queryParams to be a good solution, but the documentation on queryParams was difficult for this beginner to understand and it contains (what I think is) at least one mistake that held me up for a long time while I figured it out.

It didn’t take much code to get this working, just a lot of guessing and trying, so I thought I’d add my knowledge to the (vast, mostly out-of-date now that it’s 2016) library of Ember queryParms knowledge out there on the internet. Hopefully this helps someone.

About this tutorial

In this guide, I’m going to show you how I used queryParams in Ember to distinguish the “new” state from the “edit” state on the same route (“basics”).

About the example app

This guide uses my Ember app, “Classis”, for many of its examples, which you can explore in full on Github (it’s a work in progress but the queryParams part is done on the “basics” route if you want to look at the app that inspired this post).

“Classis” is a (fake) web app where people sell “seats” in classes they teach: tutoring, dog training, etc. It’s a lot like listing a room on AirBnB, dog boarding on Rover.com, etc. Think of classes as products people are selling, and you’ve got the idea. I call refer to “classes” as “products” in this tutorial to cut down on confusion with the programming concept, but they are called classes in my app. 

About queryParams in the context of editing records

You can use queryParams for lots of things. This particular guide shows you how to use them for editing records that have ids.

If the user is trying to edit an existing record, we can get its id and pass it along to the route where the user will edit that record. If the route sees you gave it the id, it will behave differently.

The “I’m making a new one” url looks like this:


The “hey, I’m editing a specific one” url looks like this:


Pass the queryParam from somewhere

There are lots of ways to pass a queryParam around, but in my case, I needed to pass it from an “Edit” button contained within a “class-card” component. That component’s job is to display a user’s completed product, and one “class-card” is displayed for each product the user has. Product data is passed into a class-card, and that product data includes the id.

Basically, I have a product with an id. The component knows about the product’s data, including its id. I want to pass that id to the basics page where I will edit the basic info about a product.

(I simplified the styling classes in this example and bolded the relevant part)


{{#link-to 'basics' (query-params id=class.id) class="mdl-button"}}

Now the class id (product id) will get sent to the ‘basics’ route.

You can also pass queryParams on a transition in, say, an action. Here’s a hypothetical action method I made just for this post, it’s not in my app anywhere but I included it here in case you need to pass a queryParam from an action:

goToBasics() {
  const route = this;
  const id = this.controller.get('id') || '';
  route.replaceWith('basics', {queryParams: {id: id}});

Define the queryParam on the “parent” controller

There are many ways to structure an Ember app, and I can’t claim to know them all. I do know, however, that my app uses application.js as its parent controller, so this is where I defined queryParams.

That definition looks like:


import Ember from 'ember';

export default Ember.Controller.extend({
 queryParams: ['id']

On a complex app, you might bury this deeper down inside the app, so that (perhaps) user ids don’t get confused with product ids or whatever, but on this simple app, the parent-most parent can handle it.

Add the queryParam to the route in router.js

All of my app’s routes are defined in app/router.js.  ‘basics’ is the route that you can pass an id to to distinguish “new” from “editing”.

Contrast with location/:id, which treats id as a dynamic segment (link goes to Ember documentation on the subject).

I included this here to illustrate the difference, because it’s easy to confuse the two (like I did when I was getting started with this stuff).


Router.map(function() {
  this.route('basics', {queryParams: 'id'}); //queryParam
  this.route('location', {path: 'location/:id'}); //dynamic segment

Url with a query param looks like:


Url with a dynamic id segment looks like:


Long explanation of why I did it this way:

In my app, the user goes from basics to location, in that order. Basics is the first page the user encounters. It can be used to either create a new record or edit an existing. Location, by contrast, is always used to edit a record that exists, because that record was created by basics, the page before it. If you’re on /location, it’s because you are making changes to a record that has already been created, even if you’re entering location data for the first time.

In Ember, having some understanding of what order pages are encountered in can help you make these sorts of architectural decisions (at least, until your designer decides location should come first, then you get to change this stuff or maybe handle everything with a queryParam in the first place, or whatever makes sense for your app).

Add the queryParam to the route itself

Basics is where the user edits “name” and “description” of an individual product.

Inside Route.extend, define the queryParms object like so:


export default Ember.Route.extend({
  queryParams: {
    id: {refreshModel: true}

Now /basics knows that it might sometimes get passed an id, and if it does, it should refresh its model.

Get the queryParams inside the model

!!This part was hard to figure out!!

Ember’s documentation just shows one parameter passed into model, but try as I might, param just came in as a useless empty { } object. I could see my queryParam in the url, but I couldn’t get at it from param.

After much Googling, I found the answer: the queryParams are on the second parameter accessed by model, which you can name transition:

(still in) routes/basics.js (right below the queryParams object you just made)

//queryParams are contained inside transition, which has to be passed as    the 2nd parameter to model

  model(param, transition) {
    let id = transition.queryParams.id;
    if (id) {
      return this.store.peekRecord('class', id);


I’m not sure if it’s my Ember newbieness or an actual oversight in the 1.13 documentation, but model(…) {…} totally takes more than one parameter and the second one contains that sweet, sweet queryParam you passed in.

The code in my example above looks at transition, sees if it contains an id, and if it has an id, it gets the matching ‘class’ record out of the store.

A lot of Ember tutorials perpetuate the idea that if you do model(param), the queryParam will be accessible on it, so maybe this worked at one point in Ember’s history or I just set it up wrong in mine.

Curiously enough, the guide to model hooks that enlightened me to the transition parameter also says there’s a third parameter for model straight up called “queryParams”(!!!), but in my case, that third parameter comes in empty. Only the second parameter (transition) had anything useful. I cannot explain this, I’m just reporting it in case it’s useful to someone else. (Maybe someday I will understand all of Ember’s mysteries.)

Load existing record data in setupController (but only if it exists)

Almost there: let’s load that model data into the controller now that we have it.

(still in) routes/basics.js (below the model method) 

setupController(controller, model) {
  let application = this.controllerFor('application');
  application.set('pageTitle', 'Basics');

  if (model) {
    //we're editing an existing class
    this.controller.set('existingClass', model);
    this.controller.set('editingExisting', true);
    this.controller.set('title', model.get('title'));
    this.controller.set('description', model.get('description'));
  } else {
    //this is a new class
    this.controller.set('title', '');
    this.controller.set('description', '');

Now, when we visit /basics with a queryParam in our URL, we’ll see our product’s title and description! If we visit /basics without a queryParam, title and description will be empty.

We are almost done…

Update the existing Ember record if we’re editing an existing one, create a new record if it’s a new one

Finally, we need to tell our route what to do when continuing past this page. If we have a queryParam, we want to update that record and move on to /location. If we don’t have a queryParam, we want to make a new record and move on to /location.

routes/basics.js (in the action hash now) 

actions: {

  transitionToNext(newClass) {
    console.log("going to location");
    this.replaceWith('location', newClass);

  failure() {

  continue() {

    //editing an existing class
    if (this.controller.get('editingExisting')) {
      let existingClass = this.controller.get('existingClass');
      existingClass.set('title', this.controller.get('title'));
      existingClass.set('description', this.controller.get('description'));

      existingClass.save().then(() => {
        //go to location and pass along the this existing class's id
        this.replaceWith('location', existingClass.get('id'));

  } else {

    //making a new class
    var newClass = this.store.createRecord('class', {
      title: this.controller.get('title'),
      description: this.controller.get('description')

    newClass.save().then(() => {
      //pass along the newly created class's id
      this.replaceWith('location', newClass.get('id'));

It’s the biggest block of code in this guide but it’s straightforward: if you have the editingExisting flag set in the setupController, set the updates and move onto location. If you don’t have this flag, make a new record.

Debugging advice

If you get stuck, remember you can look in the Ember Inspector to see if your records actually exist and confirm that they have the IDs you expect.


You can also console log the id at various points in your code to see if it’s coming where you expect it to.

You can also display the id in the template, which I found helpful in confirming that what I was seeing was indeed, what I was getting, like so:


I click EDIT and that same ID is now in the url:


That’s it!

This post was inspired by my work on a personal project I keep publicly available here on github – check it out if you’re new to Ember and want to see a relatively simple Ember app demonstrating queryParams and other concepts.

Ember: Making a set of radio buttons that change a value set on the controller

This guide was written for Ember 1.13


So, Ember doesn’t have anything in the way of built-in radio buttons, but there’s a great add-on called ember-radio-button, which you can install via ember-cli:

ember install ember-radio-button

In this particular tutorial, we’ll use ember-radio-button to set up two radio buttons that work as a pair (so only one can be “on” at a time) and set a variable on your controller based on which one the user picks. We will also set one of the radio buttons to be on by default.

Like this:


This guide assumes you already have a template (yourpage.hbs) and a corresponding route (yourpage.js) to work in.

In Ember, adding your code to templates and routes is kind of chicken-and-eggy (where to start?), but I tend to start in the template (.hbs) file.

In your route’s .hbs file

Use the {{#radio-button}} label {{/radio-button}} syntax if you want labels for your radio buttons (which you probably do).

This will give you two side-by-side radio buttons:


  • value is what will get automagically passed to the controller when you click this radio button
  • groupValue should match across all radio buttons in the set, or your radio buttons won’t know to un-select themselves when you click a different one
  • changed is the action method called when this radio button is clicked

When the user clicks one of these radio buttons, flavorToggled(choice) will be called and the value passed to it as choice will be “vanilla” or “chocolate”.

In your route’s .js file

Add a new action to your action hash. You can call “choice” anything you want (or omit it entirely if you don’t need a passed-in value for whatever reason).

The value that gets passed in here as “choice” was taken from the radio button’s “value” property.

actions: {
  flavorToggled(choice) {
    console.log("changing flavor choice", choice);
    this.controller.set('flavor', choice);

If you want one of these radio buttons to be checked by default, you can do that in the setupController in your .js file like so:

setupController() {
  this.controller.set('flavor', "vanilla");

All done!

That’s all there is to it! The documentation that comes with ember-radio-button shows a few more things this tutorial did not cover. Thanks, yapplabs!


Ember: Making a button component that calls an action

This guide uses Ember version 1.13.


I recently started a new Ember 1.13 app to explore Google’s Material Design Lite style library. I use Ember in my day job, too, and something that has always stuck out to me as “should be easy but isn’t” in Ember is making a button component that calls an action. 

I wanted a “continue button” component that…

  • can be re-used throughout my app
  • calls an action customized per route (ie: the continue button on the ‘basics’ route goes to the ‘location’ route, the continue button on the ‘location’ route goes to the ‘students’ route, etc)

This was surprisingly unintuitive in Ember. I expected to pass an action into the component from the parent template and have the component know where to find that action.

What not to do

I think many people who try to put an action on a component start with something like this. Note that this approach doesn’t actually work:


{{bad-example-button action=”wontWork”}}


actions: {
  wontWork() {
    console.log("you'll never see this!");

What’s missing? The call to the route’s action has to come from the component itself.

The rest of this guide will show you what does work for getting a component to fire an action on the parent’s route in Ember.

Generating the button component

Do this step inside your Ember project directory (assuming you are using ember-cli):

ember generate component continue-button

In the route’s template

First, add the component into your .hbs template. The action it calls, “continue”, needs to be defined in the action hash in this route’s .js file.


{{continue-button actionToCall="continue"}}

In the route’s js file

In your route’s .js file, create an action hash if you don’t have one already (actions: {…}) and put a “continue” method inside it. I like to stick a console log in here, too, on the first try so I have something to look for in Chrome to confirm it’s working.


actions: {
  continue() {
    console.log("continuing on to location page");

Code for the button component

When you generated the button component you got an .hbs template file and a .js file.


The important piece here is that the <button> tag contains {{action “doButtonThing”}}.

<button {{action "doButtonThing"}} class="mdl-button mdl-js-button mdl-button--raised mdl-button--accent">Continue</button>


doButtonThing is an action on the component’s own action hash. When you call doButtonThing, it’s going to fire a sendAction that references the actionToCall defined up on the component in the route template.

import Ember from 'ember';

export default Ember.Component.extend({
  actions: {
    doButtonThing() {

Yes, this is confusing as #$*! and I’ve not seen a better way to do this in my year or so of developing in Ember. It feels very much like a child (the component’s .js) is telling a parent (the route’s .js) what to do.

Another way to think of it

The {{continue-button …}} up in basics.hbs knows what to do when clicked (call “continue” action in basics.js) but it’s not going to do it until told to do it. It sits around listening for the “fire!” command.

When the user clicks the button, the code on the button component itself has its own action to call. That action yells “fire!” to the instance of the button waiting up there on the route. The {{continue-button …}} up in basics.hbs hears the fire command, delivered from the component itself in the form of a send-action.

There is no “passing” of an action into the component, it’s more like a pairing of broadcaster and listener. 

The Ember community calls the larger concept at work here “data down, actions up” which took me a while to internalize. You can read more about DDAU here.

What to change in MaxCDN settings after you change web hosts

I just moved one of my blogs to a new host (yay!). This blog uses MaxCDN for its content delivery, and moving the blog to a new host messed up the site’s styles and it took me a while (plus some back and forth with support) to get everything fixed because MaxCDN was still referencing the old host.


In case I ever do this again, here’s what needed to be done to move my WordPress blog to a new host with MaxCDN as my content delivery network.

Step 1: Add a CNAME record to your new host

My new host has CPanel (Digital Ocean, by contrast, had a Networking tab with a link to Domains and their records were accessible through there). If you have CPanel, click on Simple DNS Zone Editor.

Add a new CNAME record. It’ll probably look something like this:



(Your CPanel might add the . at the end of name for you, and it might autocomplete for you if you just type the subdomain portion and then tab out of the field.)

MaxCDN has good documentation on updating CNAME records for a variety of hosts, too.

Note: I use a custom domain in MaxCDN because I don’t want it to use the default “business name” URL that MaxCDn gives you.

Step 2: Update the Origin IP over in MaxCDN’s settings for your pull zone

Go to Zones > Pull Zones > Settings and get into that particular pull zone’s settings. At the bottom is Origin Information. Check the checkbox and enter the IP address for your new host. Click Update button to save.

Step 3: Whitelist your new IP

Go into your Account > look under the API section > click Manage > add your new IP as a whitelist IP.

You may also need to whitelist your own IP address, if you get problems with cURL requests failing when you try to clear CDN cache.

Step 4: Update your WP caching plugin

You may need to reconfigure your WP cache plugin. I use W3 Total Cache which, for reasons unbeknownst to me, likes to replace my entry for “Replace site’s hostname with:” with the word “Array” instead of the URL I give it.

For reference, “Replace site’s hostname with:” should be followed by your cdn url, like cdn1.yoursite.com.

Step 5: Purge all caches and check your site

When you’ve done all of the above, purge your CDN cache and your WP cache via your caching plugin.

It might also help to flush your local DNS. I’m on Windows and I do that in a command prompt with ipconfig /flushdns

Open a Chrome incognito tab and load your site – if your styles and images load, you’re good to go. If your site looks incomplete, look in the console for an error message. I found many of them (like 502 bad gateway) to be covered in MaxCDN’s documentation.

More tools for debugging DNS, caching issues

If you’re having problems, try these tools:

Did it propagate yet? Whatsmydns.net is a great way to check propagation and see what is actually getting served when you try to hit your CDN’s URL.

If you are using a custom domain with MaxCDN like I am, then putting that custom domain into whatsmydns should yield the actual “business” domain in the results list. In other words, if you search for cdn1.yourcustomdomain.com and you get responses of cdn1.yourbusiness.netdna-cdn.com, you’ve got it set up correctly.

What’s your site’s IP? In a command prompt / Terminal window, ping yoursite.com to get its IP address.

Is your CDN URL responding? In a command prompt / Terminal window, ping cdn1.yourcustomdomain.com and see if you get anything. If it can’t find your host, this could indicate an error with your CNAME record with your new hosting service.

Are you seeing stale or current stuff in your browser? I use Chrome incognito because each window starts with a fresh cache and no cookies. CTRL SHIFT N opens up a new incognito window.

You may also want to flush your DNS in between tests. ipconfig /flushdns does this in Windows.

If all else fails, email MaxCDN’s customer support. Even on a US holiday, I got a response within 20 minutes and they helped me get things working again.


Tutorial: Easily move a WordPress site to a new host with minimal downtime using UpdraftPlus

Moving a WordPress site from one host to another with minimal of downtime doesn’t have to be a huge hassle, and it’s easy to do it yourself even if you aren’t a web developer. Here is the process I use to move a WordPress site to a new host, with about 10 minutes or less of actual downtime (and because of caching, many visitors during the migration may not even see the outage).

I like this method because:

  • It’s easy
  • You don’t have to mess around in MySQL
  • It’s free
  • It’s maybe 10 minutes of downtime for your site, depending how fast you can upload your backup and how much you have to do to get your caching plugin/CDN (if you have them) on board with the new IP address

Before you begin, make sure you have:

  • A WordPress site on your current host
  • Access to your new hosting account (preferably with CPanel and phpMyAdmin to get the most out of this guide)
  • Access to your domain’s DNS records (yoursite.com may be registered with your current host, or a separate registrar)
  • Nameservers for your new host (they usually look like ns1.newhost.com)
  • FTP access to old host and new host via your choice of FTP software (I use Filezilla) *optional* – you can do the same stuff through your host’s CPanel File Manager if they have it
  • About an hour of time to dedicate to reading this guide and the actual migration

Step 1: Install UpdraftPlus plugin on your site


Log into your WordPress dashboard (http://yoursite.com/wp-admin) and install the free UpdraftPlus plugin.

This plugin is awesome and I recommend it for use outside of just moving your WordPress site to a new host. Here’s why:

  • The backup files do actually work (this plugin has saved my ass a couple times now)
  • You can use it to make a manual backup of your site at any time
  • You can set it up to create automatic backups and put them on the cloud storage service of your choice (personally, I back up to Google Drive)

Step 2: Use UpdraftPlus to make a backup of your site

Use Backup Now to start the backup process.


I like to do this right before I’m ready to start the migration process, so the backups are as fresh as can be.

Step 3: Download your backup files

Go back to your UpdraftPlus plugin page and go to the Existing Backups tab. Find today’s date and click each of the buttons (database, plugins, themes, uploads, others).


Updraft will prepare each backup file for you (there are 5 total). Wait for Updraft to prepare the files, then click Download to your computer for each one.


You’ll get 5 compressed files:


Step 4: Set up an account with your new host and install WordPress there

If you haven’t done so yet, sign up for an account at your new host.

I’m digging SiteGround as my host these days, and I’ve already moved several of my sites to SiteGround (including my top money-making blog).

I use the StartUp package for my up-and-coming sites, and the GoGeek plan for my top performers. You can upgrade your plan at any time as a site grows. I especially like the GoGeek plan because they throw in SSL for free (or at least they did for my first year) and because it has a separate staging environment for testing stuff on a copy of the site before pushing it live.

Next, install WordPress on your new host. Many modern hosts (including SiteGround and BlueHost) have an easy one-click install for WordPress nowadays – look in the CPanel or just the dashboard in general once you’re logged in.

Don’t worry about picking a login/password you want to use in the long run, your Updraft backups will replace whatever you choose during setup with whatever your existing site already has. Do write down whatever name/password you choose here, you’ll need it to access your new WP install until you overwrite it with your backups.


It’ll probably tell you the installation was successful and you can go see it at the following url, but that link won’t work because you haven’t updated your domain’s nameservers yet.

Step 5: Change your domain’s nameservers

I do this in dynadot.com’s domain manager because that’s where my domain is managed, but your domain may be attached to your old hosting. In any case, change its two nameservers from ns1.oldhost.com and ns2.oldhost.com to ns1.newhost.com and ns2.newhost.com (or similar).

It should propagate fairly quickly (check it here: https://www.whatsmydns.net/) but it may take a while to see the change on your machine. One way to speed it up (on Windows, anyway) is to open a command prompt (cmd) and type ipconfig /flushdns.

Load your site again (in an Incognito window in Chrome or after clearing browser cache) and you should now see your new WP install.

Step 6: Install UpdraftPlus on your new blog and restore backups

Now that you have dashboard access to your new WordPress installation, install UpdraftPlus and click Restore.


Drag your 5 files here and wait for them to upload.


When those are done uploading, click Restore.


Follow the prompts until you’re force to re-log in to your site. It should now look exactly like it used to on your old host, but you can confirm that it’s actually on your new host by pinging it in a command prompt or Terminal window (ping yoursite.com). If the IP address returned matches your new host’s, you’re good to go.

Extra step for CDN users:

I’m on MaxCDN, but regardless of what CDN you use (if you use one) there will probably be some additional setup steps to make sure your existing CDN account references your new IP and host.

I went through this process for MaxCDN and documented it here: http://www.tilcode.com/what-to-change-in-maxcdn-settings-after-you-change-web-hosts/

Step 7: You may need to do some other setup on your new host

Leave your old host active for a little while while you confirm everything’s working on your new site over the next couple days.

You may need to move the following separately:

  • Email accounts. If you had email accounts set up at your old host, take note that they don’t come with the Updraft migration and you’ll have to recreate them (and redo any redirects) on your new host.
  • Favicon: if your site had a custom favicon sitting in your site’s root directory, you might need to copy it from your old host and upload it to your new one
  • Google Analytics .html file: If you put any .html files for analytics tracking (Google Analytics is the one I always have to move manually) in your old site’s root folder, you will have to copy them to your new host
  • Robots.txt and anything else sitting in root (this will vary by site)
  • Images or other media in dedicated folders: Anything that’s part of your site but not part of WordPress will have to be manually moved. For me, this is sometimes a site logo or images on the site that I keep in a separate images folder, not uploaded to WordPress’s file manager.

If you’re afraid of losing anything off your old site, take the time now to download a copy of its entire directory off your old host, before you shut down your old hosting account. That way, if you find something missing later on, at least you can dig around the old files and maybe find it.

How to fix ‘Error establishing database connection’ in WordPress on shared hosting, VPS hosting

Error establishing database connection is my most hated WordPress problem – it’s so cryptic and so many things can cause it. I run about a dozen WordPress blogs: some are on shared hosting, some are on virtual private servers (with Digital Ocean), and nearly all of them have had this problem at some time or another. This article documents what I do when it happens to me.

If it’s any comfort, I’ve never not solved this problem (eventually). It’s definitely fixable, but there are a lot of things that can cause it, so if nothing here helps you just keep digging around in the Googles – and good luck.

Before you do anything, turn on error messages and see what the problem actually is

Get into your website’s files, either through FTP or your host’s control panel, and turn on debug mode in wp-config.php. This file is in your WordPress installation directory.

Change this line to true:

define('WP_DEBUG', true);

Now go back to http://sitename.com/wp-admin and get those juicy error messages.

This step alone can save you a lot of frustration as you debug the actual cause of your WordPress blog’s Error Establishing Database Connection problem.

Possible fix #1: make sure DB_USER and DB_PASSWORD match what your host has

The vast majority of the times I run into Error Establishing Database Connection on a shared hosting site, it’s because something (I don’t know what) caused the DB_PASSWORD in wp-config.php to become out of sync with the password my host has for that user. This particular flavor of the error connecting to db problem seems to only affect my sites that are on shared hosting (most recently, it happened to a site I host on lunarpages.com). 

Basically, what wp-config.php has for DB_USER and DB_PASSWORD has to match what your host has saved for that database and particular user.

By turning on WP_DEBUG in step 2, I was privy to the following error messages when attempting to access http://mysite.com/wp-admin:

Warning: mysqli_real_connect(): (HY000/1045): Access denied for user 'x2_artblog'@'localhost' (using password: YES) in /home/x2/public_html/blog/wp-includes/wp-db.php on line 1488

Warning: mysql_connect(): Access denied for user 'x2_artblog'@'localhost' (using password: YES) in /home/x2/public_html/blog/wp-includes/wp-db.php on line 1518

If this looks like your problem, then for some reason, your WP database login credentials are fubar.

The credentials it’s trying to use are in wp-config.php (keep this file open, the following steps will help you fix it):

// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define('DB_NAME', 'x2_artblog');

/** MySQL database username */
define('DB_USER', 'x2_artblog');

/** MySQL database password */
define('DB_PASSWORD', '123xyz456abc');

If you know what your DB_USER and DB_PASSWORD are supposed to be, maybe you’ll spot a discrepancy here. Chances are, you don’t know what’s supposed to go here, so you can’t tell just by looking if it’s right. That’s okay, I don’t either, but it’s easy to get everything matching.

First, if you have CPanel on your host, you can log into CPanel and go into MySQL Databases to see a list of users associated with your database(s).


Next, find your database and look in the Privileged Users column. One name from the Privileged Users column has to match the username given in wp-config.php.


If the user your wp-config.php file is expecting is already in this column, you’re good to go to the next step where you reset its password.

If you don’t have the same user your wp-config.php expects, either add that user here or change wp-config.php to reference a user you do have.

Still on the MySQL Databases page, scroll down into “Current Users” and find the user your db is using. Click Set Password. 


I just change the user’s password to something randomly generated, it doesn’t matter. Copy that password and paste it right into wp-config.php

/** MySQL database password */
define('DB_PASSWORD', '123xyz456abc');

Save wp-config.php (and upload it via FTP if you aren’t doing this edit directly through your hosting CPanel).

Try the site again: if it works now, you’ve resolved your “access denied” error and may now have full access to your WordPress site again.

Possible fix #2: it could be a bad plugin

This one is easy to test the fix for but I’ve only seen it be the problem once, and it happened right after I messed with plugins so the cause was obvious. However, with more plugins and WP things going to “auto update” these days, I could see how this might crop up independent of blog-owner interaction.

Rename the plugins folder.

I log into my site’s file manager via my hosting service’s website or FTP, navigate to /wp-content and rename the folder called plugins. (Don’t delete it, just put an X at the end or something.)

plugins > pluginsX

Try the site again – if it loads, your problem is one of your plugins. You can narrow it down by renaming plugins back to its normal name and then turning plugins off in groups to narrow it down to a specific one.

If your site doesn’t load, put plugins back to normal and go to the next step.

Possible fix #3: maybe your MySQL service croaked – try restarting it

This particular flavor of “Error Establishing Database Connection” seems to affect my Digital Ocean (VPS) hosted blogs (not my shared hosting blogs).  There are many reasons why MySQL can crash, but when your WP site is down and you’re losing money by the hour, getting it back online is probably your #1 priority. 

Since my Digital Ocean hosting runs on Linux, I log in to the virtual console and check if mysql is running with this command:

mysqladmin -u root -p status

This command brought MySQL back up:

service mysql start

Now, as to why it crashed in the first place, that could be any number of things, and chances are, MySQL will go right back down again as soon as the same conditions return.

The various fixes I’ve applied in effort to stop chronic MySQL crashes on Digital Ocean merit their own article someday, but for the sake of helping anyone who might find this, here’s a brief overview of stuff I’ve done on my VPS WordPress to try to stop frequent MySQL crashes.

I tried to figure out what was using up memory by logging into my droplet’s virtual console and looking at all the active processes sorted by what resources they are consuming. The command to see that chart is top.

Here’s the steps to sort what’s in top by memory usage:


f key

arrow down (to highlight %mem)

s key (to select %mem)

escape key (to return to process list)

You should now see your process list sorted with the most memory intensive processes at the top. What you find here will help you Google for solutions.


For me, mysqld is always at the top, soaking up all the memory, so I focused on that when I was trying to fix chronic “Error Establishing Database Connection” problems on my Digital Ocean WordPress blog. After mysqld was always a whole ton of apache2 instances.

Some of the stuff I did…

Went into apache2.conf and added this code to help protect against brute force attacks:

<files xmlrpc.php> 
order allow,deny 
deny from all 

This alone did not stop MySQL crashing, it crashed a few weeks later. So then I did…

I edited /etc/my.cnf to increase buffer pool size and set max_connections to 200 (this line was commented out, previously).

## Edit /etc/my.cnf, and add the following line under the [mysqld] heading.

These fixes also did not stop it, but I had another few weeks of uptime following them.

I edited /etc/apache2.conf, changing maxKeepAliveRequests from 100 to 9 because it seemed like a good way to limit how much memory apache was allowed to take up. Be sure to run service apache2 restart after editing to apply changes.

Restarting the droplet has helped, too. One time I cleared my blog’s MaxCDN cache and that immediately took the site down and replaced it with Error Establishing Database Connection. When that happened, restarting the droplet brought it back up.

To be honest, MySQL crashes on Digital Ocean are kind of an ongoing issue for my most popular WordPress blog, but I’ve managed to lengthen the time between crashes/restarts with the above steps.

Even more help with WordPress db error (articles, threads, etc)

WPBeginner has the Internet’s de facto go-to article on the subject, and they also report that somehow the database credentials on their shared host site got reset. They also have some solutions I’ve never had work for me but are worth looking into if nothing in this article worked for you.

This thread has plenty of one-off posters coming in to share their various fixes for the problem and is also worth a look if you’re stuck.

Oh, and be sure to put this line in wp-config.php back to false:

define('WP_DEBUG', false);

CSS: Hide “spinners” (up/down arrows) on inputs with type=”number” using a class

Quick (and potentially dirty) CSS fix for getting rid of “spinners” in input boxes that are type=”number” using a class to restrict the change to just one input element instead of every input in your app.

These little arrows look different on every browser (or they used to, anyway – they look pretty consistent across Chrome, Firefox, and Safari nowadays).  There’s no one-size-fits-all fix for hiding them because different browsers handle them differently.

Screen Shot 2016-04-08 at 7.35.23 AM
These ugly little things don’t even fit properly in the default input field on my browser!

Anyway, here’s the code I’ve recycled across a couple projects now to get rid of them:

JSFiddle: https://jsfiddle.net/faz7wm43/1/
Tested in Firefox 31, Chrome 48, Safari 9.0.3 on Mac and Chrome 48 on iPhone.

/* hide up/down arrows ("spinners") on input fields marked type="number" */
.no-spinners {

.no-spinners::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;

Put the no-spinners class on your input themselves.

<input type="number" class="no-spinners"/>

Full disclosure: I didn’t test this on IE.

JavaScript and Regex: Using a regular expression and .replace() to strip (foo) from a string

Here’s a quick tutorial on using regular expressions in JavaScript to edit a string and return the modified result. My strings looked like this:

"Toyota (1999 - 2005)"
"Ford (1995 and up)"
"Honda (up to 2015)"
"Kia or Chevy (any)

In this case, each string was the name property on an object. (Ie: you’re not looking at an array of strings in the example above.)

For display purposes, I wanted to show (in my app’s template) only what came before the first parenthesis, like so:

Kia or Chevy

Thanks to guide on how to use regex to remove everything after a particular character, and this refresher on how .replace() works, I had this problem solved in a matter of minutes with the following expression, where params[0] is the string (more about why my method looks like this after the code):

export function stripParensFromCarData(params/*, hash*/) {
  return params[0].replace(/\(.*\)/,'');

I used this method in an Ember helper I wrote to format strings for display in a handlebars template. The helper was hooked up like so in the .hbs file:

{{strip-parens-from-car-data carString}}

My favorite tool for testing regular expressions as I write them is regexr.com.

WordPress + MaxCDN + W3 Total Cache broken styles on main page fix

I recently hooked up one of my WordPress blogs to use MaxCDN (set up via the W3 Total Cache plugin) for serving stylesheets, images, and other things. Everything was going great except the main page of my blog was completely unstyled. Curiously enough, all of the other posts of my site had styling.

The console output in Chrome was a little help, showing me that the page was trying to find the .css and .js files at http://array/wp-content and http://array/wp-includes.

The “missing file” error stack looked like this:

GET http://array/wp-content/themes/blognametheme/style.css?ver=2.2.7 net::ERR_NAME_NOT_RESOLVED
GET http://array/wp-includes/css/dashicons.min.css?ver=4.4.2 net::ERR_NAME_NOT_RESOLVED
GET http://array/wp-content/plugins/jetpack/css/jetpack.css?ver=3.9.4 net::ERR_NAME_NOT_RESOLVED
GET http://array/wp-includes/js/jquery/jquery.js?ver=1.11.3 net::ERR_NAME_NOT_RESOLVED
GET http://array/wp-includes/js/jquery/jquery-migrate.min.js?ver=1.2.1 net::ERR_NAME_NOT_RESOLVED
GET http://array/wp-content/plugins/jetpack/modules/wpgroho.js?ver=4.4.2 net::ERR_NAME_NOT_RESOLVED

Basically, 20 minutes of Googling and reading about W3 and caching later, it dawned on me that the problem might be minification. I unchecked minification in W3 Total Cache and now it works.


Moral of the story: if you get some weird styling or jquery issues on your WordPress blog, try unchecking minify in W3 Total Cache.

Where is the WordPress installation directory on Digital Ocean?

On Digital Ocean, assuming you did their fast install when you set up your droplet, the WordPress installation is located in /var/www


This is also:

  • where your .htaccess file lives
  • where you upload your .html file for Google Analytics
  • where you’ll find the folder for uploading your theme (wp-content/themes/ThemeNameHere) – or where you can directly upload updates to its .php or .css files without having to re-zip the whole thing