If code or text you save with wp_insert_post() loses its backslashes (\d+ turns into d+, C:\Users into C:Users), the cause is not your string. These functions unslash their input, so you have to pass slashed data. Wrap the data in wp_slash() before you save it.
The symptom
I hit this while saving posts with code blocks from PHP code on a WordPress site. Commands and regular expressions in the code blocks lost every backslash, so the published code was wrong without any error or warning.
Minimal reproduction
I saved the same string three ways and read it back. The test string was C:\Users\test \d+ \n end (24 characters). I ran it on a WordPress site that reported version 7.1.3, using a throw-away draft that I then moved to the trash.
| Function | Without wp_slash() | With wp_slash() |
|---|---|---|
wp_insert_post() | C:Userstest d+ n end (20 characters) | Unchanged, 24 characters |
wp_update_post() | C:Userstest d+ n end | Unchanged |
update_post_meta() | C:Userstest d+ n end | Unchanged |
Every backslash was removed when the data was not slashed, and every backslash was kept when I wrapped the same data in wp_slash().
The fix
$post_id = wp_insert_post( wp_slash( array(
'post_title' => 'My title',
'post_content' => $content, // may contain backslashes
'post_status' => 'draft',
) ), true );The same applies to updates and to post meta.
wp_update_post( wp_slash( array(
'ID' => $post_id,
'post_content' => $content,
) ) );
update_post_meta( $post_id, 'my_key', wp_slash( $value ) );Why it happens
- The wp_insert_post reference page shows the source marking the data array as expected to be slashed and calling
wp_unslash()on it before the database write. The same page notes that thewp_insert_post_datafilter receives slashed data. - The wp_slash reference page says to use it when preparing data for core APIs that expect slashed data.
- So if you pass raw data,
wp_insert_post()unslashes it and the backslashes are consumed as escape characters.
Things to watch for
- Apply
wp_slash()to the whole array you pass, not to individual values you also use somewhere else. It returns a new value and does not change the original. - The data you read back with
get_post()is already unslashed, so do not wrap it inwp_slash()just to display it. - Code blocks are the most common place to see it, because shell commands, regular expressions and Windows paths are full of backslashes.
What I did not test
- I tested calls from PHP code only. I did not test the REST API, WP-CLI or the block editor.
- I tested one WordPress version (7.1.3 as reported by the site).
- I did not test what happens when data is slashed twice.
Sources: wp_insert_post and wp_slash in the WordPress developer reference.