Cum să generezi/actualizezi o hartă de site XML fără pluginuri?
Îmi place să codific totul manual pe site-urile mele WordPress, fără a folosi pluginuri. Există vreo modalitate de a genera sau actualiza sitemap-ul de fiecare dată când public/actualizez un articol pe unul dintre blogurile mele Multisite, fără a utiliza pluginuri?
Următorul cod funcționează imediat. Harta site-ului tău va apărea la adresa: https://numele-site-ului-tau.com/sitemap.xml
De fiecare dată când creezi sau actualizezi o pagină, articol sau tip de postare personalizată, acesta va apărea. Asigură-te să adaugi numele tipului tău de postare personalizată:
add_action( 'publish_post', 'ow_create_sitemap' );
add_action( 'publish_page', 'ow_create_sitemap' );
add_action( 'save_post', 'ow_create_sitemap' );
function ow_create_sitemap() {
$postsForSitemap = get_posts(array(
'numberposts' => -1,
'orderby' => 'modified',
// 'custom_post' trebuie înlocuit cu propriul tău Tip de Postare Personalizată (unul sau mai multe)
'post_type' => array( 'post', 'page', 'custom_post' ),
'order' => 'DESC'
));
$sitemap = '<?xml version="1.0" encoding="UTF-8"?>';
$sitemap .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">';
foreach( $postsForSitemap as $post ) {
setup_postdata( $post );
$postdate = explode( " ", $post->post_modified );
$sitemap .= '<url>'.
'<loc>' . get_permalink( $post->ID ) . '</loc>' .
'<lastmod>' . $postdate[0] . '</lastmod>' .
'<changefreq>monthly</changefreq>' .
'</url>';
}
$sitemap .= '</urlset>';
$fp = fopen( ABSPATH . 'sitemap.xml', 'w' );
fwrite( $fp, $sitemap );
fclose( $fp );
}

Nu sunt sigur dacă funcționează pe un site multisite, dar pentru mine funcționează perfect pe o singură instalație WordPress.
Când creezi/actualizezi orice articol sau pagină, acesta va genera un fișier sitemap.xml și va actualiza linkurile (URL-urile) cu cele mai recente modificări primele (ultima modificare).
Copiază și lipește codul de mai jos în fișierul functions.php al temei active:
/* funcție pentru a crea fișierul sitemap.xml în directorul root al site-ului */
// add_action("publish_post", "eg_create_sitemap");
// add_action("publish_page", "eg_create_sitemap");
add_action( "save_post", "eg_create_sitemap" );
function eg_create_sitemap() {
$postsForSitemap = get_posts( array(
'numberposts' => -1,
'orderby' => 'modified',
'post_type' => array( 'post', 'page' ),
'order' => 'DESC'
) );
$sitemap = '<?xml version="1.0" encoding="UTF-8"?>';
$sitemap .= "\n" . '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";
foreach( $postsForSitemap as $post ) {
setup_postdata( $post );
$postdate = explode( " ", $post->post_modified );
$sitemap .= "\t" . '<url>' . "\n" .
"\t\t" . '<loc>' . get_permalink( $post->ID ) . '</loc>' .
"\n\t\t" . '<lastmod>' . $postdate[0] . '</lastmod>' .
"\n\t\t" . '<changefreq>monthly</changefreq>' .
"\n\t" . '</url>' . "\n";
}
$sitemap .= '</urlset>';
$fp = fopen( ABSPATH . "sitemap.xml", 'w' );
fwrite( $fp, $sitemap );
fclose( $fp );
}

Cred că asta nu va funcționa pe un multisite - scrie sitemap.xml în aceeași locație pe server, așa că va exista doar un singur fișier sitemap.xml care va fi suprascris de fiecare dată când orice blog face o modificare...

Interogarea tuturor postărilor din site la fiecare salvare este o modalitate sigură de a aduce în jos un site care are o cantitate semnificativă de conținut. În plus, va face salvarea noilor postări din ce în ce mai lentă odată cu publicarea fiecărui articol nou.

@MarkKaplun - Ce ai recomanda ca alternativă la interogarea tuturor postărilor?

Înainte de a utiliza codul furnizat în răspunsul de pe w3uiguru, a trebuit să fac unele îmbunătățiri care respectă standardul acceptat pentru fișierele XML. Codul este mai jos:
/* funcție pentru a crea fișierul sitemap.xml în directorul rădăcină al site-ului */
// add_action("publish_post", "eg_create_sitemap");
// add_action("publish_page", "eg_create_sitemap");
add_action( "save_post", "eg_create_sitemap" );
function eg_create_sitemap() {
if ( str_replace( '-', '', get_option( 'gmt_offset' ) ) < 10 ) {
$tempo = '-0' . str_replace( '-', '', get_option( 'gmt_offset' ) );
} else {
$tempo = get_option( 'gmt_offset' );
}
if( strlen( $tempo ) == 3 ) { $tempo = $tempo . ':00'; }
$postsForSitemap = get_posts( array(
'numberposts' => -1,
'orderby' => 'modified',
'post_type' => array( 'post', 'page' ),
'order' => 'DESC'
) );
$sitemap .= '<?xml version="1.0" encoding="UTF-8"?>' . '<?xml-stylesheet type="text/xsl" href="' .
esc_url( home_url( '/' ) ) . 'sitemap.xsl"?>';
$sitemap .= "\n" . '<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";
$sitemap .= "\t" . '<url>' . "\n" .
"\t\t" . '<loc>' . esc_url( home_url( '/' ) ) . '</loc>' .
"\n\t\t" . '<lastmod>' . date( "Y-m-d\TH:i:s", current_time( 'timestamp', 0 ) ) . $tempo . '</lastmod>' .
"\n\t\t" . '<changefreq>daily</changefreq>' .
"\n\t\t" . '<priority>1.0</priority>' .
"\n\t" . '</url>' . "\n";
foreach( $postsForSitemap as $post ) {
setup_postdata( $post);
$postdate = explode( " ", $post->post_modified );
$sitemap .= "\t" . '<url>' . "\n" .
"\t\t" . '<loc>' . get_permalink( $post->ID ) . '</loc>' .
"\n\t\t" . '<lastmod>' . $postdate[0] . 'T' . $postdate[1] . $tempo . '</lastmod>' .
"\n\t\t" . '<changefreq>Weekly</changefreq>' .
"\n\t\t" . '<priority>0.5</priority>' .
"\n\t" . '</url>' . "\n";
}
$sitemap .= '</urlset>';
$fp = fopen( ABSPATH . "sitemap.xml", 'w' );
fwrite( $fp, $sitemap );
fclose( $fp );
}

Poți, te rog, să explici codul tău și să depui o [editare] pentru a-l reformata pentru lizibilitate? Mulțumesc

@locutor-antonio-cezar @gabriel Trebuie să schimbați Weekly
în weekly
din cauza Error 1840: Element '{http://www.sitemaps.org/schemas/sitemap/0.9}changefreq': [facet 'enumeration'] Valoarea 'Weekly' nu face parte din setul {'always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never'}
.

WordPress are o funcționalitate de sitemap XML încorporată începând cu versiunea 5.5 pe care o poți personaliza.
Vezi acest articol de blog pentru mai multe detalii și câteva exemple rapide. Aruncă o privire aici pentru a vedea o listă de hook-uri pe care le poți folosi pentru a personaliza sitemap-ul implicit.

Am modificat puțin codul de la @locutor-antonio-cezar, deoarece aveam nevoie de un caz de utilizare foarte specific. Aveam nevoie de o hartă de site special concepută pentru Google News. Care este diferența? Întreaga structură respectă regulile. În cazul meu specific, am limitat numărul de articole la 20. De asemenea, articolele mai vechi de 2 zile dispar. Poate cineva are nevoie de asta:
/* funcție pentru a crea fișierul sitemap.xml în directorul rădăcină al site-ului */
// add_action("publish_post", "eg_create_sitemap");
// add_action("publish_page", "eg_create_sitemap");
add_action( "save_post", "eg_create_sitemap" );
function eg_create_sitemap() {
if ( str_replace( '-', '', get_option( 'gmt_offset' ) ) < 10 ) {
$tempo = '-0' . str_replace( '-', '', get_option( 'gmt_offset' ) );
} else {
$tempo = get_option( 'gmt_offset' );
}
if( strlen( $tempo ) == 3 ) { $tempo = $tempo . ':00'; }
$postsForSitemap = get_posts( array(
'numberposts' => 20,
'orderby' => 'modified',
'post_type' => array( 'post', 'page' ),
'order' => 'DESC',
'date_query' => array(
'after' => date('Y-m-d', strtotime('-2 days'))
)
) );
$sitemap .= '<?xml version="1.0" encoding="UTF-8"?>';
$sitemap .= "\n" . '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">' . "\n";
foreach( $postsForSitemap as $post ) {
setup_postdata( $post);
$postdate = explode( " ", $post->post_modified );
$sitemap .= "\t" . "<url>" . "\n";
$sitemap .= "\t\t" . "<loc>" . get_permalink( $post->ID ) . '</loc>';
$sitemap .= "\t\t" . '<news:news>' . "\n";
$sitemap .= "\t\t\t" . '<news:publication>' . "\n";
$sitemap .= "\t\t\t\t" . '<news:name><![CDATA[ SITE-UL TĂU ]]></news:name>' . "\n";
$sitemap .= "\t\t\t\t" . '<news:language>LIMBA TA</news:language>' . "\n";
$sitemap .= "\t\t\t" . '</news:publication>' . "\n";
$sitemap .= "\t\t\t<news:publication_date>" . $postdate[0] . 'T' . $postdate[1] . $tempo . "</news:publication_date>\n";
$sitemap .= "\t\t\t" . '<news:title><![CDATA[' . get_the_title( $post) . ']]></news:title>' . "\n";
$sitemap .= "\t\t" . '</news:news>' . "\n";
$sitemap .= "\t" . '</url>' . "\n";
}
$sitemap .= '</urlset>';
$fp = fopen( ABSPATH . "sitemap_news.xml", 'w' );
fwrite( $fp, $sitemap );
fclose( $fp );
}
