-->

บทที่ 7 สร้างไฟล์ sitemap.php

สร้างไฟล์ sitemap.php

เป็นบทรองสุดท้ายแล้วนะครับ สำหรับบทนี้จะพูดถึงเรื่องของการสร้าง sitemap.php เพื่อนำไปใช้งานอย่างอื่นต่อไปครับ หลายคนเอาไป ping หรือว่าเอาไป submit ก็ได้ครับแล้วแต่แผน 

โดยทั่วไปแล้ว sitemap จะอัพเดทเมื่อมีกระทู้หรือว่าเนื้อหาใหม่ๆเสมอครับ ในเว็บ CMS หรือเว็บสำเร็จรูปอื่นๆ เช่น wordpress เป็นต้น แต่ด้วยสคริบของเราที่เราเขียนขึ้นมานี้ ด้วยความที่ว่าเราดึงข้อมูลมาจาก data.csv และเป็นข้อมูลตายตัว เราจะแก้ปัญหานี้อย่างไร

ส่วนตัวที่ผมทำนะครับ ผมจะทำในลักษณะที่ว่า จะให้มันแรนดอมมาซักจำนวนหนึ่ง 20-30 ชิ้น คร่าวๆ แล้วให้สลับไปเรื่อยๆ แต่ที่สำคัญอีกอย่างคือ ผมจะให้มัน random มาวันละครั้งพอครับ พูดง่ายๆ คือ ผมสร้าง sitemap มาวันละครั้งเท่านั้น และดึงสินค้ามาแค่ 20-30 ชิ้น

หลายๆคนอาจจะชินกับการ Gen Sitemap รอบเดียวเสร็จ แต่ ในส่วนนี้ผมจะทำให้ Gen หลายๆครั้งอย่างที่ผมกล่าวมานะครับ

เอาละครับ อันดับแรกต้องมาดูรูปแบบการสร้าง sitemap ก่อนว่าหน้าตาควรเป็นอย่างไร ผมยึดตามของ google นะครับ BUILD YOUR SITEMAP ที่นี่ครับ ลองเข้าไปอ่านกันได้ครับ

รูปแบบง่ายๆ น่าจะเป็นอย่างนี้นะครับ

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="https://www.sitemaps.org/schemas/sitemap/0.9"> 
  <url>
    <loc>https://www.example.com/foo.html</loc> 
  </url>
</urlset>

หลังจากที่ได้รูปแบบ แล้ว มาเริ่มเขียน php กันครับผม

เริ่มเขียน php sitemap

ผมต้องกำหนดชื่อไฟล์ก่อนครับว่าต้องเป็น sitemap.xml และจะกำหนดเวลาในการแคชแต่ละครั้งอยู่ที่ 1 วันครับ เป็นคอนเซ็บง่ายๆแหละครับ เมื่อรู้ว่าไฟล์ชื่อว่าอะไร ก็เช็คเวลาของไฟล์นั้นครับ ด้วย filemtime() ซึ่งจะเป็นการหาเวลาการแก้ไขไฟล์ครั้งหลังสุด

<?php 

$max        = 30; 
$time_cache = 86400;
$cachefile  = "sitemap.xml";

//Check Time Sitemap.xml
$chktime  = time() - @filemtime($cachefile);

if($chktime > $time_cache || !file_exists($cachefile)) {
 //Create new sitemap.xml
}else{
 //Read sitemal.xml
}

?>

สร้างไฟล์ sitemap
code สร้างไฟล์ sitemap

อธิบายพอสังเขป
ผมตั้งค่าต่างๆไว้ โดยกำหนดค่า $max เป็นค่าที่กำหนดว่าจะดึงสินค้ามาทำ sitemap กี่ชิ้น $time_cache จะตั้งเวลาให้แคชหรือว่าสร้างไฟล์ใหม่เป็นเวลาเท่าไร โดยหน่วยจะเป็นวินาทีครับ ที่ผมตั้งไว้คือ 1 วัน 60x60x24 และ ตั้งชื่อไฟล์ $cachefile โดยจะตั้งเป็น sitemap.xml ครับ

มาถึงการเช็คเวลา $chktime ผมจะเช็คเวลาโดยการเอาเวลาปัจจุบัน time() ลบเวลาแก้ไขไฟล์ล่าสุด @filemtime($cachefile)  จะได้ค่าส่วนต่างเวลามา หลังจากนั้นก้อเอามาเช็ค if กันนิดนึงครับ ว่าส่วนต่างเวลาที่หักลบมานั้น มันมากกว่าเวลา $time_cache หรือไม่ และผมยังเช็คว่าถ้าไม่มีไฟล์หรือไม่มีไฟล์ ชื่อว่า sitemap.xml ด้วยครับ โดยใช้ !file_exists($cachefile) ครับ เครื่องหมาย ! จะหมายถึงว่าไม่ครับ

ถ้าความต่างของเวลาเกิน เวลาที่ตั้งไว้ และยังไม่มีไฟล์ if($chktime > $time_cache || !file_exists($cachefile)) มันก็จะมาสร้างไฟล์ sitemap.xml ใหม่ครับ ถ้าไม่เข้าตามที่เราตั้งเกณฑ์ไว้ else มันก็จะอ่านไฟล์ sitemap.xml ครับผม

เอาลิงค์สินค้ามาวนได้แล้วครับทีนี้ แล้วเราจะวนในไหนละ

  <url>
    <loc>https://www.example.com/foo1.html</loc> 
  </url>
  <url>
    <loc>https://www.example.com/foo2.html</loc> 
  </url>
  <url>
    <loc>https://www.example.com/foo3.html</loc> 
  </url>

ประมานนี้เลยครับผม

ดูของจริงที่สคริบนะครับ Loop For จะวนจนกว่าจะครบค่า $max ที่เรากำหนดครับ วนไป random สินค้าไป


ผมดึง include 'app.php'; มาด้วยนะครับ ลืมบอกไปเพราะว่าจะใช้ function() บางตัว

//Create new sitemap.xml

 $xml = '<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="https://www.sitemaps.org/schemas/sitemap/0.9">';

 //Product Data from data.csv
 $file   = file(setting('file'));
 $date  = date('Y-m-d');

 for ($i=0; $i < $max; $i++) { 

  $id    = randid();
  $data  = explode(',', $file[$id]);
  $title = trim($data['0'], '"');

  $xml .= '
<url> 
  <loc>https://127.0.0.1/tempkaew/'.$id.'-'.cleantitle($title).'.html</loc>
  <lastmod>'.$date.'</lastmod>
  <changefreq>daily</changefreq>
  <priority>0.5</priority>
</url>';
 }

 $xml .= '
</urlset>';

 $createxml  =  fopen($cachefile, 'w'); 
        fwrite($createxml, $xml);
        fclose($createxml);

อธิบายพอสังเขป

ตัวสร้าง sitemap ตัวนี้ ผมจะ random สินค้ามาแสดงครับ ซึ่งไม่ให้เกินค่า $max ที่ตั้งไว้ และจะวนไปเรื่อยพร้อมสร้างและแปลงลิงค์ครับซึ่งเหมือนกับที่เราสร้างหน้าแรกให้เชื่อมกับหน้าสินค้าครับ

จากด้านบนนะครับผมจะประกาศค่าตัวแปร $xml ไว้ ซึ่ง จะกำหนดส่วนหัวของ sitemap xml ก่อนครับ คือส่วนนี้

 $xml = '<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="https://www.sitemaps.org/schemas/sitemap/0.9">';

หลังจากนั้นผมจะมา Loop For วนและ random สินค้าจนกว่าจะถึงค่า $max ครับ(ย้ำหน่อย) ซึ่งผมกำหนดไว้ที่ 30 ครับ และจะดึงข้อมูลเหมือนการดึงสินค้าทั้งหมดครับ แต่จะดึงมาเฉพาะ Title ครับ ใช้เท่านี้ เพราะว่าเอามาแปลงเป็นลิงค์ให้เข้าเว็บเราเฉยๆครับ หรือว่าให้มันลิงค์ไปที่หน้าสินค้าเราให้ถูกนั่นเองครับ ลิงค์ไม่ถูกน่าฮาเลยนะครับ (Gen sitmap แล้วอย่าลืมลอง)

 for ($i=0; $i < $max; $i++) { 

  $id    = randid();
  $data  = explode(',', $file[$id]);
  $title = trim($data['0'], '"');

  $xml .= '
<url> 
  <loc>https://127.0.0.1/tempkaew/'.$id.'-'.cleantitle($title).'.html</loc>
  <lastmod>'.$date.'</lastmod>
  <changefreq>daily</changefreq>
  <priority>0.5</priority>
</url>';
 }

โดยต้องกำหนด path และเป้าหมายให้ถูกต้องนะครับ <loc>https://127.0.0.1/tempkaew/'.$id.'-'.cleantitle($title).'.html</loc> ตามนี้ครับ ลิงค์ข้อมูลให้ถูก เดี๋ยว Bot ตามไปไม่เจอ งงหัวแตกเอา (ระบุลิงค์เต็มนะ)

และผมจะแทนค่าเจ้าพวกนี้ด้วย $xml .= ''; ทำไมต้อง $xml .= ทำไมไม่ $xml = เลยละ ถ้าหากเรา $xml = จะเป็นการกำหนดค่าใหม่ครับ แต่ถ้าเป็น $xml .= จะเป็นการเติมค่าเข้าไป เปรียบเทียบได้กับวางกล่องทับๆกันเรื่อยๆครับผม

เช่น
$xml = '1'; $xml = '2'; $xml = '3'; echo $xml; ผลลัพธ์ คือ 3
แต่ถ้า
$xml = '1'; $xml .= '2'; $xml .= '3'; echo $xml; ผลลัพธ์ คือ 123

แต่ตัวแรกต้อง $xml = ''; ไว้ก่อนนะครับ

หลังจากนั้นผมจะเอาค่า $xml มาสร้างไฟล์ sitemap.xml ครับ โดยใช้คำสั่งเจ้า fopen fwrite fclose นี่แหละครับ เทียบได้คือ เปิด เขียน ปิด (เปิดไฟล์แล้วอย่าลืมปิดไฟล์นะครับ)

ผมใช้คำสั่ง fopen($cachefile, 'w'); ซึ่ง w คือการ เขียนอย่างเดียวครับ ตัวแปรเหล่านี้ต้องเข้าศึกษาเพิ่มเติมที่ https://www.w3schools.com/php/func_filesystem_fopen.asp ครับ

ต่อจากนั้น

สร้างไฟล์ sitemap.php
eles ไม่ตรงตามที่เรากำหนด

ถ้ามันไม่ตรงตามี่เรากำหนด คือ มีไฟล์อยู่แล้ว และ ไฟล์ยังไม่เกินเวลาที่เรากำหนด else ให้มันอ่านค่า $cachefile หรือว่า ไฟล์ sitemap.xml นั่นเองครับ

ผลลัพธ์ที่ได้

สร้างไฟล์ sitemap
ผลที่ได้ไม่ได้เรียงสวยงาม
ผลที่ได้เมื่อผมลองรัน sitemap.php แล้วได้ดังภาพ เรียงไม่สวยเลยใช่ไหมครับ ข้อมูลจะเรียงกันหมดเลยครับ มีทางแก้ครับ มันก็เหมือน html ที่ไม่ได้กำหนด utf-8 แหละครับ คล้ายๆกันนะ


header("Content-Type: text/xml;charset=iso-8859-1");

เอาไว้หลัง <?php  ครับ บรรทัดเดียวก็สวยได้แล้วครับ
สร้างไฟล์ sitemap
เพิ่มเพียงบรรทัดเดียว
หลังจากนั้นลองรันอีกครั้ง #อย่าลืมลบ sitemap.xml ก่อนนะ เดี๋ยวรันแทบตายก็เหมือนเดิม เพราะเราตั้งค่าตั้ง 1 วันไว้
สร้างไฟล์ sitemap
sitemap ที่คุ้นตาหลายๆคน
เอาละครับทีนี้เราก็ได้ครบละเรื่อง sitemap.php ออกมาสวยเอาการ (เข้าข้างตัวเอง) ทีนี้เหลือให้รันตามลิงค์ sitemap.xml ใน htacess ครับ คือให้เรียก https://127.0.0.1/tempkaew/sitemap.xml แต่ให้มันวิ่งไปทำงานที่ sitemap.php แทนครับ

RewriteRule ^sitemap.xml$ sitemap.php [L]

บรรทัดเดียวก็พอครับ ประมาณว่า เราเรียกไฟล์ sitemap.xml มันจะทำงานโดยจะไปเช็คที่ไฟล์ sitemap.php ก่อนครับ เท่านั้นแหละการทำงานของมันครับ ที่เหลือก็ขึ้นอยู่กับ sitemap.php ที่เราเขียนมาแล้วแหละครับ

ไฟล์ sitemap.php

<?php 

header("Content-Type: text/xml;charset=iso-8859-1");

//Include Function File
include 'app.php';

$max        = 30; 
$time_cache = 86400;
$cachefile  = "sitemap.xml";

//Check Time Sitemap.xml
$chktime  = time() - @filemtime($cachefile);

if($chktime > $time_cache || !file_exists($cachefile)) {

 //Create new sitemap.xml

 $xml = '<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="https://www.sitemaps.org/schemas/sitemap/0.9">';

 //Product Data from data.csv
 $file   = file(setting('file'));
 $date  = date('Y-m-d');

 for ($i=0; $i < $max; $i++) { 

  $id    = randid();
  $data  = explode(',', $file[$id]);
  $title = trim($data['0'], '"');

  $xml .= '
<url> 
  <loc>https://127.0.0.1/tempkaew/'.$id.'-'.cleantitle($title).'.html</loc>
  <lastmod>'.$date.'</lastmod>
  <changefreq>daily</changefreq>
  <priority>0.5</priority>
</url>';
 }

 $xml .= '
</urlset>';

 $createxml  =  fopen($cachefile, 'w'); 
        fwrite($createxml, $xml);
        fclose($createxml); 

}else{

 //Read sitemal.xml
 echo file_get_contents($cachefile);

}

?>

ไฟล์ .htaccess

RewriteEngine On
RewriteRule ^([^/]*)-([^/]*)\.html$ product.php?id=$1 [L]
RewriteRule ^contact$ page-contact.php [L]
RewriteRule ^sitemap.xml$ sitemap.php [L]

หากติดข้อสงสัยสอบถามได้ครับผม