Regenerare Slug-uri Din Titlurile Articolelor
Da, este posibil.
Cod exemplu, trebuie testat și rafinat:
// obține toate articolele
$posts = get_posts( array ( 'numberposts' => -1 ) );
foreach ( $posts as $post )
{
// verifică slug-ul și actualizează dacă este necesar
$new_slug = sanitize_title( $post->post_title );
if ( $post->post_name != $new_slug )
{
wp_update_post(
array (
'ID' => $post->ID,
'post_name' => $new_slug
)
);
}
}
Acest cod este doar un exemplu rapid, pot exista unele erori și cazuri particulare neacoperite, dar ar trebui să îți ofere o idee. De asemenea, acest proces poate dura ceva timp, așa că ar putea fi util să împărți actualizarea în bucăți mai mici.

Hmmm... din experiența mea, asta nu funcționează.
Argumentul post_name
este ignorat de wp_update_post
, cel puțin în versiunea 3.9 a nucleului

În prezent, post_name
este ignorat în cadrul funcției wp_update_post()
, dar este luat în considerare când actualizarea postului apelează funcția wp_insert_post()
: asta înseamnă că transmiterea noului slug la actualizare, va avea ca rezultat schimbarea lui efectivă pentru postul care se actualizează.

@fuxia, am încercat ceva similar dar se întârzie. Ești în măsură să sugerezi o abordare?

Acest plugin face și el treaba: http://www.jerrytravis.com/598/wordpress-plugin-to-generate-post-slugs
Totuși, deoarece funcționează doar pentru articolele care nu au încă un slug, dacă ai nevoie să regenerezi slug-urile, editează următoarea linie din plugin:
if ($post->post_name == "") {
de exemplu, ai putea să o schimbi în:
if (true) {

Am încercat metoda sugerată de Toscho, care este cea "instinctivă", dar în multe cazuri nu funcționează (vezi codul sursă pentru a înțelege la ce mă refer prin "multe cazuri").
Analizând codul, am găsit filtrul wp_insert_post_data
, apelat de funcția wp_update_post
chiar înainte de inserarea postului în baza de date.
Prin apelarea acestui filtru și modificarea valorii $data['post_name']
, am reușit să fac acest lucru să funcționeze corect. WordPress este mișto, dar atât de prost documentat...
Am editat documentația, astfel încât mai mulți oameni să poată găsi această soluție dacă este necesar.

Poți să evidențiezi de ce wp_update_post suprascrie post_name? Singurul motiv pe care îl văd pentru ca acest lucru să se întâmple este dacă utilizatorul care încearcă să modifice post_name este doar un contributor (sau același nivel), caz în care nu ar trebui să permită acelui utilizator să schimbe slug-ul, ai găsit alte cazuri în care post_name este suprascris?

puteți face acest lucru direct în MySQL dacă aveți nevoie. (site-ul nostru WooCommerce are sute de mii de produse):
update wp_posts set post_name = concat(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(lower(post_title), '"', ''), "'", ''), ",", '-'), " ", '-'), "&", ''), ";", ''), "@", ''), ".", ''), ":", ''), "/", ''), "+", ''), "(", ''), ")", ''), "--", '-'), "---", '-'), "--", '-'), "--", '-'), '-', id) where post_type = 'product';
unde post_type = 'product' - asta va limita actualizarea doar la produsele WooCommerce; ar trebui să stabiliți ce limite doriți să aplicați acestei interogări.

Am avut o problemă la migrarea și combinarea mai multor tipuri de postări. Aveam și o mulțime de titluri goale. Am creat o comandă WP CLI pentru a le repara pe toate, dar iată esența a ceea ce am făcut:
global $wpdb;
$types = [
'page',
// Numele mașină ale CPT-urilor tale
];
// Formatează corect interogarea IN.
$final = array_map(function($type) {
return "'" . esc_sql($type) . "'";
}, $types);
// Selectează toate câmpurile de titlu goale.
$query = sprintf("SELECT post_title, ID FROM `%s` WHERE post_type IN (%s) AND post_name = ''",
$wpdb->posts,
implode(",", $final)
);
foreach ($wpdb->get_results($query) as $post) {
$title = sanitize_title_with_dashes( $post->post_title );
$wpdb->update('wp_posts', ['post_name' => $title], ['ID' => $post->ID]);
}
A fost necesar să fac o actualizare directă în MySQL, deoarece wp_update_post nu actualizează post_name.
