The Problem
We all have been in a situation like this, and a lot of questions on this site need a solution like this. You either have to update a database, insert a lot of data automatically, convert meta_keys
, or something similar.
Of course, in a running system based on best practises this should not happen.
But as it does, I would love to hear your personal solution to this problem, and why you chose yours.
The Question
How do you implement one-time scripts in your (running) WordPress install?
The issue here is mainly because of the following reasons:
- Scripts that insert data should not run more than one time
- Scripts that require a lot of ressources should not run at a time when they can not be monitored
- They should not be run by accident
The Reason I ask
I have got my own practise, I am going to post it in the answers. As I do not know if it is the best solution out there, I’d like to know about yours. Also, this is a question that is asked a lot of times in context of other questions, and it would be great to have a ressource collecting the ideas.
looking forward to learning from you 🙂
I for myself use a combination of:
Structure
I use a file (
onetime.php
) in my include-folderinc
, which is included in thefunctions.php
, and deleted from there after the use.The file for the script itself
In my
onetime.php
my functionf711_my_onetime_function()
is placed. As it could be any function. I assume your script is tested and works correctly.To achieve the control over the execution of the script, I use both
Capability control
To stop other users from accidentally executioning my script:
or
a transient
to stop myself from accidentally executing the script more than once.
The file for executing the script in my function
f711_my_onetime_function()
would look like that:The reason I set the transient immediately after the check if it exists is that I want the function to be executed after the script has been locked from beeing used twice.
If I need any output from my function, I either print it out as a comment in the footer, or sometimes I even filter the content.
The lockouttime is set to 10 Minutes, but can be adjusted to your needs.
Cleanup
After the successful execution of my script I delete the
include
from thefunctions.php
, and remove theonetime.php
from the server. As I used a timeout for the transient, I do not need to clean the database, but of course you could also delete the transient after you removed the file.You can also do this:
run
onetime.php
and rename it after execution.I created a command line Phing script for this, it’s nothing special other than loading an external script to run. The reason I used it via the CLI is because:
So you can use Phing, or the PHP CLI and sleep at night. The WP-CLI is also a good alternative though I forget if you can use it outside the web root.
Since this is a popular post here is an example of the script: https://github.com/wycks/WordPhing (run.php)
Under ideal conditions I’d ssh into the server and execute the function myself using wp-cli.
This often isn’t possible, though, so I tend to set a $_GET variable and hook it onto ‘init’, for instance:
then hit
and disable the hook when it’s done.
Another pretty simple way of running a one-time script is to do this by means of an MU plugin.
Put the code in some PHP file (e.g.,
one-time.php
) that you upload to your MU plugins’ folder (by default/wp-content/mu-plugins
), adjust the file permissions, run the plugin (i.e., according to your chosen hook, you basically just have to visit the frontend/backend), and you’re all done.Here is a boilerplate:
Without the comments and stuff, it just looks like this:
Definitely you can, Just create your one time code as a plugin.
Problem how do I activate this plugin without clicking Activate link?
just add
activate_plugins('onetime/index.php');
infunctions.php
or
Use must use plugins, http://codex.wordpress.org/Must_Use_Plugins
Try with different actions as when you want to execute onetime plugin,
admin_init – after admin init
init – wordpress init
wp – when wordpress loaded
Sometimes I used a function hooked on plugin deactivation.
See here Update Old Links To Pretty Permalinks Custom Post Type
Once only admins can activate plugins, there a capability check as a side effect.
There is no need to delete file once deactivated it will not included by wordress.
In addiction if you want to run again it you can. Activating and deactivating again.
And sometimes I used transient used like in @fischi answer. E.g. here query to create woocommerce products from images or here Delete/replace img tags in post content for auto published posts
A combination of both can be an alternative.
Another way is to set a global wp_option when the work is done and check for that option every time the init hook is executed.
Naturally you don’t need to have this code forever (even if it is a simple read from the database), so you can probably remove the code when the work is done.
Also you can manually change this option value to 0 if you need to re-execute the code.
My approach is a little different on this. I like to add my one-time script as a function in my theme’s function.php and run it on a specific GET query.
To run this, just visit the URL “www.sitename.com/?linkupdate”
This is working fine for me till now…
Does this method have any drawbacks? Just wondering…
I just use a single custom product template page I’m not using and isn’t connected to anything on the public server.
Like if I have a testimonial page that isn’t live (in draft mode, or whatever), but connected to a single page template, for example
single-testimonial.php
– I can place functions in there, load the page via apreview
and the function or whatever is launched once. It’s also very easy to make modifications to the function in case of debugging.Is really easy and I prefer it over using
init
because I have more control over when and how its launched. Just my preference.Just in case it helps, this is what I did and it works well:
Using wp-cli
eval-file
is great. You can even do it on a remote system (using an ‘@‘ ssh alias) with a local script.If you have your code in
one-time.php
in the wordpress base directory and you have a command line on the system you want to run against you can do:If you have the file
one-time.php
locally and you want to run it against a remote wordpress using @ it looks like this: