I work on a plugin that has WDS-Shortcodes as a dependency. Attempting to run composer install on this plugin will fail with the error message:
[RuntimeException]
Could not scan for classes inside "/public_html/wp-content/plugins/lqd-messages/vendor/webdevstudios/wds-shortcodes/vendor/tgmpa/tgm-plugin-activation/class-tgm-plugin-activation.php" which does not appear to be a file nor a folder
The problem is that this file doesn’t yet exist. Once this failure has occurred it can be remedied by going to: vendor/webdevstudios/wds-shortcodes/ and running composer install. After that you can go back up to the main project directory and run composer install again and it should succeed.
The patch for this has been made on the github repository, unfortunately it hasn’t made its way to packagist. So lets try using the repository code directly by adding the repo as a repository to our composer.json like so:
We’ll then update our require in composer.json to point to dev-master. The line "webdevstudios/wds-shortcodes": "^1.0.7", has the version number swapped out for dev-master. For kicks and giggles lets delete our vendor directory, composer.lock, and run composer clear-cache.
This time everything installs without issue (huzzah!). We pull up a page on our dev site and it crashes. Looking at the debug.log again we see:
PHP Warning: require(/public_html/wp-content/plugins/lqd-messages/vendor/composer/../webdevstudios/wds-shortcodes/vendor/jtsternberg/shortcode-button/shortcode-button.php): failed to open stream: No such file or directory in /public_html/wp-content/plugins/lqd-messages/vendor/composer/autoload_real.php on line 69
This issue arises because WDS-Shortcodes is attempting to load the shortcode-button dependency from within its own vendor folder, which doesn’t exist. The shortcode-button dependency does exist in the main plugin’s vendor folder but the composer.json for WDS-Shortcodes is hard coded to use its own vendor directory.
Okay, this is an easy fix. Run composer install from within the WDS-Shortcodes folder. Refresh our page and we are still crashing. What now?
PHP Fatal error: Class 'WDS_Shortcodes' not found in /public_html/wp-content/plugins/lqd-messages/includes/shortcodes/class-shortcodes-run-base.php on line 7
Here the problem is that Composer when it creates the autoload files doesn’t add any autoloading of WDS-Shortcodes’ files. Why not? Because WDS-Shortcodes doesn’t have any autoloading setup in its composer.json. There are two ways we can resolve this. One is to edit WDS-Shortcode’s composer.json and add to the "files" portion of "autoload": wds-shortcodes.php. But, for whatever reason, this won’t be picked up by Composer even if we do a composer dump-autoload -o, manually delete the autoload files, and run composer dump-autoload -o again. So lets leave this option for the moment.
The other way we can handle this is by editing our main plugin’s composer.json to include the autoloading specifications. This involves adding "vendor/webdevstudios/wds-shortcodes/wds-shortcodes.php" under the "files" section of "autoload".
Welp, that doesn’t work either. Lets try instead adding this file and all the files in /includes to the classmapping:
Huzzah! That works! But there was a lot of manual work to get things going. Lets try removing the path specification for shortcode-button in WDS-Shortcodes composer.json to see if we can simplify things a bit (we already have shortcode-button installed as a dependency of the main plugin). After making this edit we run composer dump-autoload -o and get an error:
PHP Parse error: syntax error, unexpected ''4cfe55868654b2ea9298a46af9d2b' (T_ENCASULATED_AND_WHITESPACE), expecting end of file in /public_html/wp-content/plugins/lqd-messages/vendor/webdevstudios/wds-shortcoes/vendor/composer/autoload_files.php in line 11
If someone wants to clue me in on exactly why this happens, I’d appreciate it. The quick way around this issue is to manually delete the composer autoload files. Once this is done one can rerun composer dump-autoload -o and composer will complete without error.
If we refresh our page that seems to have gone okay. But what if we try to actually remove the vendor/jtsternberg/shortcode_button in wds-shortcodes? I’m a glutton for punishment, let’s find out. Reloading the page seems to work!
What if we forked our own version of WDS-Shortcodes and attempted to make the changes we’ve made above to composer.json and see if we can’t avoid all this manual work? I’m game.
We update our main composer.json to point to our new repo instead of WDS’:
We’ll also delete our composer.lock and vendor files/directories and run composer clear-cache. Then, with fingers crossed, composer install. The install goes smoothly, reloading the page not as much.
PHP Fatal error: Class 'Shortcode_Button' not found in /public_html/wp-content/plugins/lqd-messages/vendor/webdevstudios/wds-shortcodes/includes/shortcode-admin.php on line 3
Ahh, that’s right, I need to add the shortcode_button as a dependency to the main composer.json file, under "require" I add: "jtsternberg/shortcode_button": "^1.0.7", just like it was in WDS-Shortcode’s composer.json previously. I go through my regular rigamarole (delete composer related files, run clear-cache) and do composer install again. Its successful but I’m still getting the same error as above.
Ahh, that’s right. I need to tell Composer to autoload the shortcode-button code, so I add the same "autoload""files" statement from WDS-Shortcode’s composer.json (okay, so I did try adding the statement to "classmap" first, but it didn’t work, so…): "vendor/jtsternberg/shortcode-button/shortcode-button.php".
Regular rigamarole, refresh, and the page loads! So this is better but still not perfect. Ideally I wouldn’t need to manually add short-button as a dependency to my plugin or tell composer to autoload the files…but for the moment, it works.
I’ve used a variety of local development environments over the years and some of them have done a decent job – but none of them have been the one. Back in January when I first saw DevKinsta announced over on WP Tavern I was excited to give it a try. I’ve finally tried it and wanted to share some thoughts and feedback on DevKinsta.
Installation (on Windows)
DevKinsta uses Docker to containerize the various services DevKinsta launches. Docker utilizes Windows Subsystem for Linux 2 (WSL2) under the hood which is part of the Windows Operating System. You’ll need to install it and Docker if you haven’t already.
The official documentation suggests you need to have Hyper-V and Containers enabled in Windows Features (Settings–>Control Panel–>Programs and Fetaures–>Turn Windows features on or off) but I have neither enabled on my system. All I have installed on my system is the Virtual Machine Platform and Windows Subsystem for Linux.
Once you have WSL2 and Docker installed and enabled you can actually install Kinsta. The Kinsta portion is straightforward.
First Installation Screen
Kinsta installs itself in Users\{user}\AppData\Local\Programs\DevKinsta which still seems a bit weird to me. But I’ve seen other apps doing this as well. I’m not a huge fan of having so many places to look for installation applications (above, Program Files, Program Files (x86), AppData\Roaming, etc.) but I’m guessing this is the new and Microsoft sanctioned way of doing things?
Choose the location for DevKinsta to install.
Once the install is complete you see the completed screen and can run DevKinsta. Woohoo!
The Completed Install Screen for DevKinsta
Running DevKinsta for the First Time
The first time you launch DevKinsta it will take a while to launch (I’m guessing at least several minutes for most folks). This is because DevKinsta is downloading the images it uses with Docker…and I do mean images plural: devkinsta_fpm, devkinsta_db, devkinsta_nginx, devkinsta_mailhog, and devkinsta_adminer (that’s five images if you weren’t counting).
DevKinsta Downloading Images. 1 / 5 indicates it is on the first of the 5 images.
After this first time things move much more quickly. The normal loading screen you’ll see is gone in a flash. I expect there will still be occasional slowish starts as Kinsta makes changes to the underlying images and these changes need to be applied to the containers running on each of our local systems.
Your Day-to-Day DevKinsta Loading Screen
Creating a New Site
Once DevKinsta is loaded you are provided with a slick UI and three big options: New WordPress site, Import from Kinsta, and Custom site.
The Create New Site Screen
Adding a new site is extremely simple. Give the site a name and provide a username and password and Kinsta takes care of the rest.
New WordPress Site Screen
Note that Kinsta is making all the decisions for you if you take this route. If you need to customize your install you’ll use the Custom Install option. Using this option you can choose a PHP version, enable HTTPS, select a specific WordPress version, create a Multisite and so on. Still pretty simple and straightforward.
Custom Site Screen in DevKinsta
The Docker Warning
At some point you’ll be warned by Docker that Docker has detected Windows files being shared into a WSL 2 container and that this may result in poor performance.
Lets break that down a little. Windows Subsystem for Linux 2 is a Windows component that provides a light Linux installation. Docker uses WSL 2 when creating containers. If you mount files from your Windows filesystem to the container (which is utilizing WSL 2) the speeds deteriorate. You really want to have your files mounted inside of the container.
I usually spin up containers from within WSL to avoid this problem but Kinsta didn’t. Why not? Because Kinsta wants you to be able to browse and edit those files in your native Windows filesystem and when they are inside the container they are available on the Linux filesystem and not the Windows filesystem.
Now technically that isn’t entirely true. You can setup a network share from which you can access files within your Linux container, but that all is a bit messy. Maybe someday they’ll add an option that allows you to have the files reside in the container rather than on the Windows side and we’ll see some performance boost, but I understand why they did it this way.
Docker Warning About Using Windows Files in WSL 2 Container
The Individual Site Dashboard
Once the setup of your new site is complete you get a nice dashboard that allows you to manage your site.
Most of the Site Dashboard Screen
The rest of the Site Dashboard Screen
You can see the features yourself so let me just point out a few of the highlights:
You can quickly open the site frontend or backend (WP Admin).
The Database Manager (Adminer) is easily accessible.
The site host provides the URL and the site path provides the file system location of your site.
You can toggle SSL/HTTPS on.
Information about the database is clearly presented allowing for easy remote access.
There is one glaring omission – there is no one click access to the terminal. Instead you’ll need to whip out some command-line expertise – or read the DevKinsta documentation.
Settings
The Settings are rather sparse – two that I think deserve attention here. First there is the option to enter a site path – this is the local filesystem location for projects. This isn’t for a specific project but for all projects overall.
The Settings Screen
The Rest of the Setting Screen
The second is configuring what you want the default username and password to be for WordPress installs. It’s a minor convenience but still nice.
Visual Studio Code Dilemma
VSC has this killer extension (err extensions) that allow one to work on remote (or virtual) systems as if they were local. Unfortunately, when you attempt to connect the kinsta_fpm container to VSC you are dropped in the root directory and the Kinsta files are nowhere to be found.
You can break out by using File–>Open Folder and navigating to /www/kinsta/public/some-site but it isn’t ideal. I’d love to see a tighter VSC integration.
How Does It Compare to Local?
Overall I’d say it compares pretty favorably to Local. Personally, I don’t like having my dev servers installed on my local host, I want them virtualized or containerized. This reduces the surface area open for attack on my local machine and helps avoid munging of my system which happens on occasion by even the best intentioned software.
How Does It Compare to VVV?
DevKinsta is simple to use and its reliance on Docker rather than Vagrant/VirtualBox is attractive to me. However, VVV still comes with more tools – PHPUnit, Xdebug, Composer, NodeJS, git, and Subversion being the most notable in my opinion.
I’d love to see these tools included with DevKinsta as well…NodeJS especially needs to be there for folks to do Gutenberg development.
Summarize/Expand on Missing
I like a lot about DevKinsta but there are some features that are missing of varying importance. I’m going to summarize up those I’ve already listed as well as add a few more below.
Provide the option to use the GUI to manage wp-env.
Low Priority
Provide option to use WSL 2 filesystem rather than native Windows filesystem to improve performance.
Low Low Priority
I’d like to see more logging detail on what DevKinsta is doing while updating my Docker containers. Not because I actually need to know but it soothes me to see the logging scrolling past indicating that no, this software has not frozen.
I’d like to see more logging detail in general without having to dig for logs.
Conclusion
DevKinsta is a solid option for a local dev environment. I’d like to see them open source it and think this would facilitate faster innovation. The lack of Gutenberg support built-in and the lack of native tooling is a big bummer for me. I’m leaning towards using wp-env at least for the moment.
The wonderful folks at Delicious Brains made SpinupWP available to the general public in May of 2019. Since everything that comes out of Delicious Brains is top notch, SpinupWP caught my eye – but there is a certain inertia that affects some of us (me) when it comes to moving sites between hosts (bit of a misnomer in this case)…so I put it off until I couldn’t bear the poor performance and support of my current web host anymore and thus I gained some ertia.
Launching a new site using SpinupWP was fairly simple and the performance was impressive! My ertia was ready to migrate my existing sites until I saw the official migration guide from SpinupWP. The steps are sysadmin’ish (nothing wrong with that), involve a number of manual and time consuming actions, and I would need to repeat them for each site I wanted to move.
My ertia inertia’ed again and I decided to stick with my current host – until their Varnish cache kept failing (even after they “fixed” it) every few minutes resulting in every site visit hitting the database. I still wasn’t ready to go through the monotonous toil involved in following the official migration instructions repeatedly, so I struck out to find a simpler way–and I’m here today to share it with you!
When To Use This Guide
The SpinupWP site migration guide offers a number of best practices which should be utilized by high traffic / high importance sites. This guide is best utilized by individuals running small or medium traffic sites where a brief period of downtime will not be an issue and where time is a more precious commodity than robust process.
I hope this guide will be particularly useful to individuals without a technical background who are running / managing WordPress sites. To this end, I have included a copious number of screenshots and have attempted to be meticulous in recording even the smallest steps involved in this process.
Assumptions
You will already need to have a SpinupWP account created and have spun up a server, see the official Getting Started documentation for information on how to do so.
Warning: Many web hosts offer email servers as part of their platform. SpinupWP does not (for good reason). You must setup a transactional email solution if you want any emails to be sent by WordPress (e.g registration, comment notification, password reset).
High-Level Overview
Before we dive into the weeds, lets take a quick look at the major steps you’ll be undertaking to migrate your existing site to SpinupWP using my “expedited” process:
Create a New Site on SpinupWP.
Update TXT records with your Domain Name Server (DNS).
Use the freemium plugin UpdraftPlus to create a backup of your existing site.
Sidebar: Using Local Storage.
Sidebar: Using Remote Storage.
Sidebar: Cleaning Up WP.
Modify your computer’s host file to use your new site.
Restore the backup taken earlier using UpdraftPlus to your new site.
Note: If you are like me, your eyes are drawn to the big pinkish button “Spin Up a New Server” and don’t immediately see an option to “Add Site”. Look underneath the pink button to find the white “Add Site” button.
You are now in the “New Site Wizard” and will setup your “Domains”.
Ensure that “Enable HTTPS (SSL/TLS certificates)” is checked and enter the domain name of the site you are migrating to SpinupWP. Usually you’ll be making two entries on this page – mydomain.com and www.mydomain.com – where domain is the name of your site and .com is the top-level domain (TLD, e.g. .com, .net, .org).
Click Next. You will are now asked “Are you ready to point your domains at this server?” The answer is “No” – for the time being we want visitors to mydomain.com to continue going to the old host and not to SpinupWP.
Click Next. You’ll be shown two sets of TXT records you need to add to your domain name server (DNS). Oftentimes your DNS is the same as your Domain Registrar. For the sake of this example (and because I think they are awesome) we’ll be using Cloudflare as our DNS.
Sidebar: Configuring DNS Records with Cloudflare
Open a new tab in your browser and go to Cloudflare’s site. In the header menu you should see a “Log In” option to the left of “Sign Up” and a big orange “Under Attack?” button, click on “Log In”.
After logging in you will be presented with the domains you have registered with Cloudflare.
Click on the appropriate domain and you’ll be brought to the Cloudflare Domain Dashboard.
Towards the top of this page you will see a number of blue and white buttons – Overview, Analytics, DNS – ahh, that’s the one! Click!
You’ll want to add two records. Click on the blue “Add record” button.
You’ll change the Type of the record to TXT and then copy from your SpinupWP tab the top left column’s content into Name. Leave TTL as is and copy into Content from the SpinupWP tab top-right column. Click Save.
Repeat this step again for the second TXT record, this will be on the SpinupWP tab and you’ll be using the bottom left column for Name and the bottom right column for Content. Click Save.
Once you’ve added these records they should now appear in Cloudflare, something like this:
End Sidebar, Resume SpinupWP Site Setup
Great work! Go back to the SpinupWP tab and click the pink “I’ve Updated the DNS” button.
SpinupWP will check the new records have been added and show a successful confirmation message:
Click Next. You’ve now completed the Domains step of the New Site wizard and moved on to Installation.
Click on WordPress and ensure the checkmark appears next to it. Then click on Next.
You’ll now need to provide some information to SpinupWP about this particular instance of WordPress. Note that the Title, Admin Username, and Admin Password will all be overwritten once you restore your site to this WordPress instance later in this process.
Note: Make sure you copy down the username and password, you’ll need these until you restore your site.
Click Next.
Congratulations! You’ve left the Installation section of the New Site Wizard and are now working with the Database section.
You’ll be creating a new database. Note that the database name, username, password, and table prefix are not overwritten when you restore your site later with UpdraftPlus, so make sure you use sensible names and save them somewhere safe!
Note: If the database you restore uses the wp_ prefix then SpinupWP retains their unique prefix, but this is only if you are using the wp_ prefix.
Click Next. Almost done!
Choose a logical user name for your site. This is the Linux user name that runs the processes and owns the files on your server.
Unless you have a reason to do otherwise, choose the latest stable release of PHP (currently 7.4) and enable the full page cache. Then Click Next!
You’ll be presented with the Confirmation Wizard page. I’ve split it into two screenshots below.
Review the listed settings. They should match what you’ve entered throughout the wizard.
Ignore the Site Migration Guide note and click “Add Site”.
Wait a second, what is this? Did I fail to setup the site? It seems as if I’ve been dropped into a similar site setup wizard?
No, you’ve successfully created the site, unfortunately the SpinupWP dashboard for your new site is confusingly presented. Click on Back to Server on the top left to feel better.
Using UpdraftPlus to Create a Backup
Now that we have a brand new WordPress install setup on SpinupWP we can actually get to work. Log in to your existing WordPress site and install the freemium UpdraftPlus plugin:
Plugins –> Add New –> Search for “UpdraftPlus” –> Install –> Activate
Once the plugin is activated it can be accessed under:
Click on the Big Blue “Backup Now” button. A modal window will open.
Make sure you have checked off “Include your database in the backup”, “Include your files in the backup”
If you have configured (see sidebar below) remote storage, ensure “Send this backup to remote storage” is checked.
Click “Backup Now” at the bottom right of the modal window.
You’ll be returned to the main UpdraftPlus page and you’ll be able to watch the progress of the backup. It should look something like this:
Once the backup has completed you’ll see the Existing Backups section has files relating to your recent backup:
If you are using remote storage you are all set!
Sidebar: Using Local Storage
If you don’t want to setup remote storage, UpdraftPlus will save the backup files to your current host. You can then download your backup files to your computer and then upload them later to the new site.
In order to download the files you need to:
Click on the button representing each type of backup data: Database, Plugins, Themes, Uploads, Others.
On the same page will appear an option to download files of a specific data type. You need to click on each file and download it to your local computer.
Note: If your site is large UpdraftPlus will break the data across multiple files. For each file listed you’ll need to click on it to download. If there are three files listed under Database you’ll need to click on each individually (another perk to using remote storage).
Sidebar: Using Remote Storage
UpdraftPlus can save your backups to your local web host or a number of remote storage options. Click on the Settings tab to the right of the Backup/Restore tab to configure remote storage.
Consumer level storage options include Dropbox, Google Drive, and Microsoft OneDrive. If you use one of these services I’d recommend using an account dedicated only to backups, separate from the account you use daily. If your site is compromised (hacked) in the future you don’t want the hackers to gain access to your files as well!
For more business oriented options Amazon S3, Microsoft Azure, and Google Cloud are available.
Select your desired remote storage provider and then Save at the bottom of the page.
You’ll be prompted to authenticate (login) to your storage provider. Once you’ve done so, UpdraftPlus will be able to backup files to and restore files from your remote storage.
Sidebar: Cleaning Up WP
Over time WP has a tendency to collect garbage. Themes we’ve forgotten to delete, plugins we no longer use, database tables or entries that are irrelevant. To speed up your site migration you can eliminate some of these files/data and thus decrease the time it takes to backup and restore.
Warning: I’d recommend taking a bloated backup first (before you make any changes!). It is far too easy to accidentally delete something you actually need.
Go through the following steps to clean things up:
Check under Appearance –> Themes for unused themes and remove.
Check under Plugins –> Installed Plugins for unused plugins and remove.
Use ADC’s Table tab Optimize option to reduce the size of your db tables.
If you are looking for a nightmare, try cleaning up the media library.
Modifying Host Files
Next we need to “restore” our site to the new WP instance we’ve created on SpinupWP. To make this easy lets change our host file so that the IP address of our SpinupWP site is set as the location of our mydomain.com.
When the “Notepad” app appears as an option, right-click on it and choose “Run as administrator”.
When prompted, allow it to run as administrator.
In Notepad go to File –> Open
Navigate to and open: c:\windows\system32\drivers\etc\hosts
macOS/Linux
Open Terminal and enter the command: sudo nano /etc/hosts
General Instructions
You’ll add a record to this text file that looks something like this:
172.217.165.142 mydomain.com
The IP address is on the left and the domain of the site you are moving is on the right. You can find your site’s new IP address in SpinupWP.
Save the File.
What Is Happening Here?
Normally when we visit a website our browser contacts a DNS server which provides the IP address for the site we want to visit. When we add a record to our hosts file we tell our computer not to use the DNS record but instead to use the information in our host file.
If you’ve made this update to your host file, when you navigate to mydomain.com you should now see your new WordPress instance and not your existing site.
IMPORTANT: You will probably need to close your browser and reopen it before this will work. It seems browsers cache the IP address.
Restore the UpdraftPlus Backup to Your New Site
With your host file updated, use your browser to visit your new sites administration page (e.g. mydomain.com/wp-admin).
Note: You’ll login with the credentials you created while adding the new site (via SpinupWP’s Add Site Wizard), not the credentials for mydomain.com you use regularly on your site.
Once logged in you need to install UpdraftPlus on this site:
Plugins –> Add New –> Search for “UpdraftPlus” –> Install –> Activate
Next we’ll navigate to the UpdraftPlus dashboard:
Settings –> UpdraftPlus Backups
Using Remote Storage
If you used remote storage to perform the backup on your old site you can restore from this remote storage to the new site.
Click on the Settings tab.
Under Remote Storage choose the same storage option you used previously.
Click Save and then authenticate with the same credentials you used previously.
Click on the Backup / Restore Tab.
Under Existing Backups click on “Rescan remote storage”.
After a minute or two you should see the backup you created earlier listed under Existing Backups. (Wife’s Editorial Comment: this would be a good time to get a snack).
Using Local Storage
If you used local storage and downloaded the backup files to your local computer you’ll need to upload them to the new site before they can be restored.
Under Existing Backups choose Upload backup files
Select all the backup files you want to upload.
After a moment your backup should appear under Existing Backups.
Performing the Actual Restore
Once you have your backup files loaded into UpdraftPlus you can click the Restore button under Actions. This will launch a restore wizard:
Ensure that all the available components are checked: Plugins, Themes, Uploads, Others, and Database.
Click Next.
You’ll be presented with the option to exclude some tables from the restore – don’t.
Click the Restore button.
Rare Problem: If, for some reason, your WordPress database tables don’t have a prefix, UpdraftPlus will restore the tables but they will not be accessible. You either need to add a prefix to your database tables before making the transfer or after. I hope to write a separate article explaining how to accomplish this soon.
UpdraftPlus will present a nice window informing you of all the activities it is taking. If successful you should eventually see a big green checkmark next to “Restore successful!”.
Click on Return to UpdraftPlus configuration.
You may be booted out to the WordPress login page.
If you aren’t automatically booted, log out of WordPress.
Log back in (mydomain.com/wp-admin) using your old site’s username and password.
Remember: When you restored the old site to your new site you overwrote the username and password you created while adding the site to SpinupWP. You’ll use your username/password from the old site going forward.
Add SpinupWP and Limit Logins Reloaded Plugins
SpinupWP automatically adds the SpinupWP and Limit Logins Reloaded plugins when you add a new site. By restoring an UpdraftPlus backup you have deleted these plugins.
Go to Plugins –> Add New –> Search for “SpinupWP”
Install –> Activate.
Go back to Plugins –> Add New –> Search for “Limit Logins Reloaded”
Install –> Activate.
That was easy!
Update Your DNS Server
Okay, to be honest, we aren’t just updating the DNS server. There are a few related steps we’ll be taking as well, but I promise they’ll only take a minute!
You want to visit your site and make sure everything looks/works as expected. You could spend a lot of time here, that’s up to you.
Once you’ve confirmed the site is working properly you should comment out the line we added earlier to your hosts file. The result should look something like this: # 172.217.165.142 mydomain.com
Now you can go update your DNS records. You’ll be replacing the IP address in your mydomain.com and www.mydomain.com records with that of your new site’s IP.
Close out your browser and reopen it (or use another browser). You want to make sure the browser is not still using the IP you set in the host file.
Load up your site, it should be nice and snappy on SpinupWP’s service. Congratulations! You’ve successfully migrated your site to SpinupWP.
Tip: Make sure you remove any unnecessary plugins once you’ve migrated to SpinupWP, this includes any caching plugins you may have been using on your previous host.
Instructions on overcoming a default value error when attempting to convert a MyISAM table to InnoDB.
Recently I noticed one of my older WP site still had some MyISAM tables. These days most folks are running InnoDB due to its advantages over MyISAM. If your WP database is using MyISAM you should probably update to InnoDB as well (ummm, make sure there isn’t some reason you need to stay on MyISAM first!).
Changing the engine for a table should be fairly simple:
ALTER TABLE dbname.prefix_users ENGINE=InnoDB;
But when I tried this I received an unfriendly error about an “Invalid Default Value” in a datetime column.
Ends up MySQL is now more strict in what it allows in a datetime field and it doesn’t like values of all zeroes. An easy way to fix this is to temporarily disable this strictness when running our query. This is controlled in our sql_mode. To get the current values of your MySQL sql_mode:
SELECT @@sql_mode
You want to remove from this list NO_ZERO_IN_DATE and NO_ZERO_DATE. To do this we will use
SET sql_mode = '<listofvalues>';
Replace <listofvalues> with the results of your SELECT @@sql_mode above making sure to remove NO_ZERO_IN_DATE and NO_ZERO_DATE from the list.
You should end up with something like:
SET sql_mode = 'IGNORE_SPACE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
Put this before your ALTER TABLE statement and this time when you execute the command it should succeed. In sum, you should be running a query that looks something like this:
SET sql_mode = 'IGNORE_SPACE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
ALTER TABLE dbname.prefix_users ENGINE=InnoDB;
Hope this helps someone else who finds themselves in the same situation!
For step-by-step instructions on using WordPress as a headless back-end with Gatsby as the front-end see the GitHub repo
Interesting Note: We’ll be looking particularly at static site generators (SSGs) of which Matt Mullenweg is not a fan.
What is Headless?
Some confusion regarding terms due to inconsistent use within community (which tends to happen):
In a generic sense, “head” is the front-end (UI) of a site (do we actually use it that way?) so “headless” is a site without a front-end.
“Headless” sites have existed in the WordPress ecosystem using the REST API.
More recently, the term has been used in association with Static Site Generators (SSG’s) such as Gatsby, where WP serves as the back-end (“headless”) and Gatsby serves as the front-end (“head”).
While other languages (Go: Hugo, Ruby: Jekyll) provide SSG’s, the most popular are in JS and these are often referred to as using the Jamstack (JavaScript, API, Markdown).
Why Use Headless?
Performance Gains
Scalability
Reduced Cost (at scale)
Security Improvements
Decoupled UI
Use Latest JS Frameworks
Separation of Concerns (SoC)
Downsides of Headless
Now maintaining two separate sites – WP back-end and front-end.
The complexity of front-end frameworks (e.g. React) reduces productivity in the short-term.
Loss of plugin functionality (most WP plugins won’t work in a static environment).
(1) complicated setup, (2) must setup CDN, (3) redirects via meta tags (not 301/302), (4) AJAX doesn’t work, (5) WP Contact Forms plugins don’t work, (6) native WP search must be replaced, (7) WP comments don’t work, (8) can take a long time to deploy, (9) responsible for security, (10) must manually create 404 pages, (11) support issues.
All sites are installed in a Local Sites folder at a path something like C:\Users\username\Local Sites.
The software itself is installed at:
C:\Program Files (x86)\Local\
You can find the component server software used by Local in the extraResources subdirectory. nginx, php, mysql, mariadb, and mailhog are yet one level deeper inside lighting-services.
Within the specific server software folder you’ll probably need to find the desired binary (e.g. if you are confusing a code editor). For me this looks like: \php-7.3.5+6\bin\win64\php.exe.
Note, however that you’ll want to edit the configuration files inside of your specific Project within Local Sites. For example, php.ini can be edited at \Local Sites\nameofsite\conf\php\php.ini.hbs.
Why .hbs? This seems to be the extension for Handlebars Templates and while I normally think of Handlebars being for templating code it apparently can also be used in config files, thus allowing for dynamic values in Local’s config files.
Turning Off PHP Debugging for Local
~/Local Sites/nameofsite/conf/php/php.ini.hbs
Change display_errors = On to display_errors = Off.
Configuring Local to Work with Composer
Composer won’t detect Local’s PHP by default, need to navigate to it manually. Path should be something like: C:\Program Files (x86)\Local\resources\extraResources\lightning-services\php-7.3.5+6\bin\win64\php.exe.
Don’t allow Composer to setup php.ini file.
I’ve been unable to get Composer running with Local with either the Windows Composer installer (see towards bottom of page) or the manual method. The problem appears to be that the local provided PHP binary was compiled without SSL support.
Unfortunately, it isn’t as easy as passing an o
What Local Is
Local, under the hood, appears to be a fairly straightforward XAMP setup (where X is Windows, Linux, or MacOS). Don’t get me wrong, the UI layer is beautiful and overall its wonderful to worth with.
It utilizes Google’s SwiftShader, a “high-performance CPU-based implementation of the Vulkan, OpenGL ES, and Direct3D 9 graphics APIs.”
In addition to the fundamental packages of nginx (web server), PHP (language server), and MySQL/MariaDB (database servers) it bundles the following with the install:
I’ve used a wide variety of local dev environment solutions. From WAMP to Docker to Vagrant they have all had their benefits and limitations. I don’t expect to find the perfect solution.
The one I’ve been using for perhaps a year now is VVV, which uses Vagrant under the hood. There are challenges with using it but I’m fairly comfortable with it and at the moment the limitations of Local are too significant for me to make the switch.
FWIW, I’ve outlined the salient issues below:
Closed Source – Local, unlike most other local dev solutions, is closed source. I’m not against using commercial software but being oss is generally a boon, imho.
Premium – Most other local dev solutions are also free. Local’s basic version comes for free but they have a premium version that costs $20/mo. This makes more uncomfortable than a solution that is premium only. freemium’s have a tendency to move basic functionality from the free edition to the premium edition when they don’t see the desired uptake of their premium edition. I’m not saying that will happen with Local, only that it makes me nervous.
Speed – While theoretically Local should be faster than virtual options I haven’t found this to be significantly true. VVV is no speed demon in my experience, but neither is Local. Whatever small amount of performance I might gain isn’t worth the cost in migrating to Local.
Native – In general I prefer my tools to be as portable and self-contained as possible. This means I favor solutions that use virtualization technologies under the hood…Local used to but has now adopted a native approach. Since 3 doesn’t seem to be a huge win (at least for me), 4 becomes a bigger problem.
Compatibility – This is actually the nail in the coffin for me. All of the others I could probably live with but the inability to use certain core development tools with Local (on Windows) just doesn’t work. Specifically, I have been unable to discover how to get Composer working with Local.
Maybe no one is like me, but I’ve tripped over this same mistake several times now and hope I can spare you the trouble.
In order to configure Gatsby to work with WordPress you use a Gatsby (not WordPress) plugin called gatsby-source-wordpress. You can then write a GraphQL query to pull data from your WordPress site.
Try running gatsby develop and you may run into the same errors I encountered.
ERROR #85923 GRAPHQL There was an error in your GraphQL query: Cannot query field "allWordPressPost" on type "Query".
ERROR #98123 WEBPACK Generating development JavaScript bundle failed... Cannot query field "allWordPressPost" on type "Query".
The likely reason Gatsby is throwing these errors is because you used allWordPressPost in your query instead of allWordpressPost. See the difference? In Gatsby you DON’T capitalize the letter p.
Its that simple…and yet that makes it all the more easy to overlook.
Sabai Apps makes a Directories Pro development version available. The current version (as of 9/24/18 EST) is 1.2.0-dev77.
They provide the commits from git, but this can be a bit messy to read…and I find writing things down helps me solidify things in my memory. Since I’m already writing it down for my own purposes (to solidify in memory, to familiarize with code, to be able to return to later), I figured I’d share it with anyone else who might be interested (yes, is that 1 other person I see?!).
I should note that while I think these are cleaner/easier to read that the original git commit logs they are also limited in their own ways:
I’ve probably mixed things up somewhere, maybe multiple somewheres.
I don’t provide full file paths and sometimes there are multiple files with the same name in different paths (I assume from context which one is being referred to can be discerned, or that one can refer to the git commit log).
I sometimes choose to skip over items (e.g., spelling corrections, but also things I find for whatever reason less relevant).
I often don’t list JS files that have changed, only the PHP files.
I’m only providing notes on some of the plugin components in Directories Pro (e.g., no payments), so notes are incomplete.
Sometimes (like with dev72) not all of the commit logs are loading, so I can only provide partial updates.
Understanding these limitations, I still think you can get a pretty good idea pretty quickly of what is going on. For those interested in reading the original git commit logs:
Added BuddyPress activity support to listings/reviews and its comments. (ContentTypesHelper)
Moved BNFW related functions to a helper class. (BnfwHelper)
22nd
Prefix Directories admin notice messages with [directories]. (Platform)
Add rel=”noopener” to links with target=”_blank”. (UserIdentityHtmlHelper, DefaultRenderer, WhatsAppRenderer)
Added check if directory exists. (TemplateElement)
Refactoring code. (OptionsField)
Add link to location API registration sites. (AlgoliaAutocompleteApi, GeoNamesTimezoneApi, MapboxGeocodingApi)
21st
Output log messages while importing. (WPAllImport/Importer)
Fixed global Exception instances not being caught (LocationCSVImporter).
Refactored code. (LocationCSVImporter, ApiHelper)
Ensure geocoding API returns 2-character uppercase country code. (GoogleMapsGeocodingApi, MapboxGeocodingApi, NominatimGeocodingApi)
Fixed invalid timezone API request URL. (GeoNamesTimezoneApi)
Fixed CSV importer/exporter not handling Timezone column. (LocationCSVExporter, LocationCSVImporter)
20th
More code for WP All Import add-on. (EntityImporter, FieldImporter, IWpAllImporter, MapImporter, SocialImporter, WPImporter, Import, functions.php, LocationCSVImporter, LocationComponent)
No longer stops processing video field when fetching thumbail has failed. (VideoType)
Refactoring. (RangeType)
Do not show time selection field. (FeaturedFieldWidget)
Moved payment CSV import/export classes to directories-payments plugin. (CSVComponent, PaymentExporter, PaymentImporter)
19th
More code for WP All Import add-on. (FieldImporter, MapImporter, WordPressContentComponent, EntityImporter, SocialImporter, WPImporter, WPAllImport/Importer)
Allow passing custom setting value for each search form field. (FormHelper).
Bump version. (FieldImporter)
Fixed taxonomy term page not showing correct content on certain occasion. (Platform)
Allow city/province values to be entered through input text fields (AddressFieldWidget, AddressFormField).
Fixed address column not always being populated (AddressFieldTYpe).
6th
Fixed array to string conversion PHP error (AdminElementHelper).
Now allows other map/location fields to be used to display listings on map (MapViewMode, location_entities.html.php, location_entities_container.json.php, LocationComponent).
Fixed status dropdown not showing up on dashboard (NavHelper).
Added new no_content bundle info key (Bundle).
Set default admin bundle path if not set (AbstractBundleType).
Do not include internal type bundles in content type options (ReferenceFieldType).
Sync reference fields on create entity success event (EntityComponent).
Fetch values for structured data properties from taxonomy terms (AddressFieldType).
July
30th
Use template to customize single post type page (Platform).
Fixed hidden address fields not being filled (AddressFormField).
29th
Added filter to force is_page on category archive page (Platform).
28th
Enabled import/export of voting_vote type fields (VotingExporter, VotingImporter).
Imported vote value must always be a PHP array (VotingImporter).
Customize Slick to prevent conflict with themes (photoslider.js, slick.custom.js, slick.js, SliderHelper, PhotoSliderViewMode).
Updated leaflet JS library files.
27th
Fixed missing argument warning error (Platform).
26th
Fixed unmerged code (DropdownButtonLinksHelper).
Prefix data-toggle attribute with app name (Dashboard, DropDownButtonLinksHelper, TabsElement, ButtonsField, CheckboxField, ColorPaletteField, EditorField, RadiosField, MapFieldRenderer, dashboard_dashbaord.html.php).
Change prefix of data-toggle from app name to BS prefix (Dashboard, dashboard_dashboard.html.php).
24th
Load scripts in footer by default (GoogleMapsApi, ApiHelper, AbstractGoogleMapsApi, GeoNamesTimezoneApi, MapboxGeocodingApi, NominatimGeocodingApi, LeafletMapApi).
Fix bundle info referencing current value instead of default info (Edit).
Fix icon not being imported for each option through CSV import (OptionsField).
Moved Fieldset component to new directories-fieldset project (AddFieldset, Fieldsets, FieldsetEntityBundleType, FieldsetEntity, FieldsetEntityType, FieldsetComponent).
23rd
Use -sabai_app_fullname- placeholder instead of hardcoded “directories” (AddDirectory, DeleteDirectory, Directories, EditDirectory, DirectoryComponent, TypesHelper, ElementsFormField, AdminContent, WordPressContentComponent, DirectoryProComponent).
Add check for internal type bundles (ContentTypes, ContentTypesHelper).
Make sure BundlesHelper always returns an array (BundlesHelper).
Skip filtering by entity type on bundles since names are always unique (EntityComponent).
Accept URL for any social account field (SocialComponent).
Fixed review body field being displayed at top (ReviewEntityBundleType).
Added new Fieldset compoennt (AddFieldset, Fieldsets, FieldsetEntityBundleType, FieldsetEntity, FieldsetEntityType, FieldsetComponent).
21st
Added link target option to screenshot field renderer (FieldDisplayelement, AbstractRenderer, ImageRenderer, ScreenshotFieldRenderer).
Fixed setting is_singular to true on archive page causing SEO issues (Platform).
Fixed parent entity name/link not appearing when posting child entity (AddChildEntity).
Load scripts in footer by default (AbstractPostDisplayButton, ApiHelper, SliderHelper).
20th
Fixed fatal error where 7th parameter is not being an array (ElementsFormField, AdminElementHelper).
Fixed streetview not working (map-googlemaps.js).
19th
Properly close file opened with finfo_open() (FileTypeHelper).
Fixed fatal error when rendering screenshot image as background (ImageRenderer).
18th
Added link to URL option (ImageRenderer, ScreenshotFieldRenderer).
Added filter to customize default No Image image (NoImageHelper).
Force check un-updated components on plugin update (Platform).
Added fix for single term page not rendering properly with some themes (Platform).
Removed console debug data (location-field.js).
Fixed invalid method param type (ScreenshotFieldRenderer).
17th
Fixed custom bundle info value disappearing on directory update (ReviewComponent, EntityComponent, Bundle, WordPressContentComponent, ContactComponent, LocationComponent).
16th
Fixed render as background option not working in certain case (ImageRenderer); later this change was reverted.
Add new Recalculate Review Ratings tool (RecalculateRatingsHelper, ReviewComponent).
No caching reviews on listing page by default (directory_listing_displays.php).
Fix custom formatted address not showing when no location term assigned (AddressFieldRenderer).
Fixed photoslider zoom setting overriding photoslider link setting (photoslider_entities.html.php, PhotoSliderViewMode).
Added option to add country restriction to geocoding API (GeoNamesTimezoneApi, GoogleMapsAutocompelteApi, GoogleMapsGeocodingApi).
6th
Made changes to parameters for Entity_Field_options helper (FieldHelper, PersonalDataHelper, AbstractMode, ContactComponent, OpenNowDisplayLabel, PhotoSliderFieldRenderer).