ส่วนหัวและหมวดหมู่ของ WordPress ฟังก์ชัน wp_list_categories คลาส PHP เพื่อการทำงานที่สะดวกและปลอดภัยกับ MySQL หมวด Useless php

ในบทความนี้ (ระดับผู้ดูแลเว็บ - ขั้นสูง) เราจะพูดถึงสิ่งที่เรียกว่าจุดตัดในรูปแบบต่างๆ การนำทาง "เหลี่ยมเพชรพลอย" เพื่อให้การดูดซึมเนื้อหาง่ายขึ้น ฉันแนะนำให้อ่านบทความ Wikipedia เรื่อง "การจำแนก Facet" และสิ่งพิมพ์เกี่ยวกับ ภาษาอังกฤษ(แต่มีรูปภาพด้วย!) "ออกแบบการนำทางแบบเหลี่ยมมุมที่ดีขึ้นสำหรับเว็บไซต์ของคุณ"

การนำทางแบบเหลี่ยมเพชรพลอยพร้อมการกรองตามสีหรือ ช่วงราคาอาจมีประโยชน์สำหรับผู้เข้าชมของคุณ แต่มักจะเป็นอันตรายในการค้นหา เนื่องจากสร้างที่อยู่หลายชุดพร้อมเนื้อหาที่ซ้ำกัน เนื่องจากซ้ำกัน เครื่องมือค้นหาจะไม่สามารถสแกนไซต์อย่างรวดเร็วเพื่อดูการอัปเดตเนื้อหา ซึ่งจะส่งผลต่อการจัดทำดัชนี เพื่อลดปัญหานี้และช่วยให้ผู้ดูแลเว็บทำให้การค้นหาการนำทางแบบประกอบเป็นเรื่องง่าย เราต้องการ:

เหมาะสำหรับผู้ใช้และการค้นหาโดย Google

เส้นทางที่ชัดเจนไปยังหน้าผลิตภัณฑ์/บทความ:

การแสดง URL สำหรับหน้าหมวดหมู่:
http://www.example.com/category.php?category=gummy-candies

การแสดง URL เฉพาะผลิตภัณฑ์:
http://www.example.com/product.php?item=swedish-fish

รายการซ้ำที่ไม่ต้องการเกิดจากการนำทางแบบประกอบ

หน้าเดียวกันสามารถเข้าถึงได้จากที่อยู่เว็บที่แตกต่างกัน:

หน้า Canonical



URL: example.com/product.php? item=ปลาสวีเดน

หน้าซ้ำกัน



URL:example.com/product.php? item=swedish-fish&category=gummy-candies&price=5-10


Category=gummy-candies&taste=เปรี้ยว&ราคา=5-10

ข้อผิดพลาด:

  • ไม่มีประโยชน์สำหรับ Google เนื่องจากผู้ใช้ไม่ค่อยค้นหา [แยมผิวส้มราคา 9:55 ดอลลาร์]
  • ไม่มีความหมายสำหรับโปรแกรมรวบรวมข้อมูลที่จะพบรายการเดียวกัน ("สลัดผลไม้") จากหน้าหมวดหมู่หลัก (อาจเป็น "Jummy" หรือ "Sour Gummy")
  • จุดลบสำหรับเจ้าของไซต์ เนื่องจากคำขอจัดทำดัชนีจะเจือจางด้วยหมวดหมู่เดียวกันหลายเวอร์ชัน
  • จุดลบสำหรับเจ้าของเว็บไซต์เนื่องจากไม่มีประโยชน์และเป็นภาระเพิ่มเติม แบนด์วิธเว็บไซต์
หน้าว่าง:


URL: example.com/category.php? Category=gummy-candies&taste=sour&price=over-10

ข้อผิดพลาด:

  • รหัสสำหรับเครื่องมือค้นหาส่งคืนไม่ถูกต้อง (ในกรณีนี้ หน้าเว็บควรส่งคืนรหัส 404)
  • หน้าว่างสำหรับผู้ใช้


วิธีแก้ปัญหาที่แย่ที่สุด (ไม่เป็นมิตรกับการค้นหา) สำหรับการนำทางแบบประกอบ

ตัวอย่างหมายเลข 1: พารามิเตอร์ที่ไม่เป็นมาตรฐานจะถูกใช้เป็นส่วนหนึ่งของ URL: เครื่องหมายจุลภาคและวงเล็บแทน คีย์=ค่า&:

  • example.com/category? [ category:gummy-candy ][ sort:ราคาต่ำไปสูง ][ sid:789 ]
  • example.com/category?category , gummy-candy , sort , lowtohigh , sid , 789
วิธี:
example.com/category? category=gummy-candy&sort=ต่ำไปสูง&sid=789

ตัวอย่างหมายเลข 2: การใช้ไดเร็กทอรีหรือพาธของไฟล์แทนพารามิเตอร์ในรายการค่าที่ไม่เปลี่ยนเนื้อหาของเพจ:
example.com/c123 /s789/ product?swedish-fish
(โดยที่ /c123/ category, /s789/ session ID ซึ่งไม่เปลี่ยนเนื้อหาของหน้า)

ทางออกที่ดี:

  • example.com /gummy-candy/ product?item=swedish-fish&sid=789(ไดเร็กทอรี /gummy-candy/ เปลี่ยนแปลงเนื้อหาของเพจอย่างมีความหมาย)
ทางออกที่ดีที่สุด:
  • example.com/product?item=swedish-fish& Category=gummy-candy&sid=789 (พารามิเตอร์ URL ให้ความยืดหยุ่นมากขึ้นสำหรับเครื่องมือค้นหาเพื่อกำหนดวิธีการรวบรวมข้อมูลอย่างมีประสิทธิภาพ)
เป็นเรื่องยากสำหรับโปรแกรมรวบรวมข้อมูลที่จะแยกความแตกต่างค่าที่มีประโยชน์ (เช่น "gummy-candy") จากค่าที่ไม่มีประโยชน์ (เช่น "SESSIONID") เมื่อค่าเหล่านี้ถูกวางไว้โดยตรงในเส้นทางลิงก์ ในทางกลับกัน พารามิเตอร์ URL ให้ความยืดหยุ่นสำหรับเครื่องมือค้นหาในการทดสอบและกำหนดอย่างรวดเร็วเมื่อค่าที่กำหนดไม่จำเป็นต้องให้โปรแกรมรวบรวมข้อมูลเข้าถึงตัวเลือกทั้งหมด

ค่าทั่วไปที่ไม่เปลี่ยนแปลงเนื้อหาของเพจและต้องแสดงเป็นพารามิเตอร์ URL ได้แก่:

  • รหัสเซสชัน
  • การติดตามรหัส
  • รหัสผู้อ้างอิง
  • การประทับเวลา
ตัวอย่างหมายเลข 3: แปลงค่าที่ผู้ใช้สร้างขึ้น (อาจเป็นอนันต์) เป็นพารามิเตอร์ URL ที่สามารถรวบรวมข้อมูลและจัดทำดัชนีได้ แต่ไม่มีประโยชน์สำหรับการค้นหา
การใช้ข้อมูลรองที่สร้างโดยผู้ใช้ไซต์ (เช่น ลองจิจูด/ละติจูด หรือ "วันที่ผ่านมา") ใน URL ที่รวบรวมข้อมูลและจัดทำดัชนี:
  • example.com/find-a-doctor? รัศมี=15&ละติจูด=40.7565068&ลองจิจูด=-73.9668408
  • example.com/article?category=health&วันที่แล้ว=7
วิธี:
  • example.com/find-a-doctor? city=san-francisco&neighborhood=soma
  • example.com/articles?category=health& วันที่=มกราคม-10-2014
แทนที่จะอนุญาตให้ผู้ใช้สร้างค่าเพื่อสร้าง URL ที่รวบรวมข้อมูลได้ (ซึ่งส่งผลให้มีความเป็นไปได้ไม่รู้จบโดยมีมูลค่าน้อยมากสำหรับผู้เยี่ยมชม) จะเป็นการดีกว่าที่จะเผยแพร่หมวดหมู่เพจสำหรับค่าที่ได้รับความนิยมสูงสุด นอกจากนี้คุณยังสามารถรวมไว้ด้วย ข้อมูลเพิ่มเติมเพื่อให้หน้าเว็บมีคุณค่ามากกว่าหน้าผลการค้นหาทั่วไป หรือคุณอาจพิจารณาวางค่าที่ผู้ใช้สร้างขึ้นในไดเร็กทอรีแยกต่างหาก จากนั้นใช้ robots.txt เพื่อป้องกันการรวบรวมข้อมูลจากไดเร็กทอรีนั้น
  • ตัวอย่าง.com /กรอง/หาหมอ?radius=15&latitude=40.7565068&longitude=-73.9668408
  • ตัวอย่าง.com /กรอง/บทความ?category=health&days-ago=7
และใน robots.txt:
ตัวแทนผู้ใช้: *
ไม่อนุญาต: /กรอง/

ตัวอย่างหมายเลข 4- การเพิ่มพารามิเตอร์ URL โดยไม่มีตรรกะ

  • ตัวอย่าง.com /gummy-candy/อมยิ้ม/gummy-candy/กัมมี่-แคนดี้/ผลิตภัณฑ์สวีเดน-ปลา
  • example.com/product? cat=gummy-candy&cat=lollipops&cat=gummy-candy&cat=gummy-candy&item=ปลาสวีดิช
ทางออกที่ดี:
  • example.com /gummy-candy/ product?item=swedish-fish
ทางออกที่ดีที่สุด:
  • example.com/product? item=swedish-fish&category=gummy-candy
พารามิเตอร์ URL ที่ไม่เกี่ยวข้องมีแต่เพิ่มความซ้ำซ้อน ทำให้เว็บไซต์ได้รับการรวบรวมข้อมูลและจัดทำดัชนีได้อย่างมีประสิทธิภาพน้อยลง ดังนั้นจึงจำเป็นต้องกำจัดพารามิเตอร์ URL ที่ไม่จำเป็นออกและล้างลิงก์ขยะเป็นระยะก่อนที่จะสร้าง URL ใหม่ หากเซสชันผู้ใช้จำเป็นต้องมีพารามิเตอร์จำนวนมาก คุณสามารถซ่อนข้อมูลในคุกกี้แทนที่จะเพิ่มค่าอย่างต่อเนื่อง เช่น cat=gummy-candy&cat=อมยิ้ม&cat=gummy-candy& ...

ตัวอย่างหมายเลข 5: แนะนำการปรับแต่งเพิ่มเติม (การกรอง) เมื่อมีผลลัพธ์เป็นโมฆะ

ห่วย:
อนุญาตให้ผู้ใช้เลือกตัวกรองเมื่อมีรายการว่างที่ต้องปรับแต่ง


ชี้แจงหน้าเว็บที่ไม่มีผลลัพธ์ (เช่น ราคา=เกิน 10) ซึ่งทำให้ผู้ใช้หงุดหงิดและทำให้เกิดการร้องขอที่ไม่จำเป็นสำหรับเครื่องมือค้นหา

วิธี:
สร้างลิงก์เฉพาะเมื่อมีองค์ประกอบให้ผู้ใช้เลือกเท่านั้น หากผลลัพธ์เป็นศูนย์ ลิงก์จะถูกทำเครื่องหมายเป็น "สีเทา" (เช่น ไม่สามารถคลิกได้) หากต้องการปรับปรุงการใช้งานให้ดียิ่งขึ้น ให้พิจารณารวมตัวบ่งชี้จำนวนรายการที่มีอยู่ไว้ข้างตัวกรองแต่ละตัว


ไม่อนุญาตให้แสดงหน้าเว็บที่ไม่มีผลลัพธ์ (เช่น ราคา=เกิน 10) นอกจากนี้ ผู้ใช้ไม่ได้รับอนุญาตให้คลิกที่ไม่จำเป็น และเครื่องมือค้นหาไม่ได้รับอนุญาตให้รวบรวมข้อมูลหน้าเว็บที่ไม่มีประโยชน์นี้

มีความจำเป็นต้องป้องกันการปรากฏที่อยู่ที่ไม่จำเป็นและลดพื้นที่สำหรับผู้เข้าชมโดยการสร้าง URL เฉพาะเมื่อมีผลิตภัณฑ์เท่านั้น วิธีนี้จะช่วยให้ผู้ใช้มีส่วนร่วมกับไซต์ของคุณ (คลิกปุ่มย้อนกลับน้อยลงเมื่อไม่พบผลิตภัณฑ์) และจะลดจำนวน URL ที่เป็นไปได้ที่เครื่องมือค้นหารู้จัก นอกจากนี้ หากหน้าเว็บไม่ได้เป็นเพียง "สินค้าหมดชั่วคราว" แต่ไม่น่าจะมีข้อมูลที่เกี่ยวข้องเลย คุณอาจต้องพิจารณาให้รหัสตอบกลับ 404 แก่หน้านั้น ในหน้า 404 คุณสามารถสร้างได้ ข้อความที่เป็นประโยชน์สำหรับผู้ใช้ด้วย จำนวนมากตัวเลือกในการนำทางหรือช่องค้นหาเพื่อให้ผู้ใช้สามารถค้นหาผลิตภัณฑ์ที่เกี่ยวข้องได้

สำหรับไซต์ใหม่ที่ผู้ดูแลเว็บกำลังพิจารณาใช้การนำทางแบบประกอบ มีหลายตัวเลือกในการเพิ่มประสิทธิภาพการรวบรวมข้อมูล (ชุดที่อยู่ในไซต์ของคุณที่ Google รู้จัก) ของหน้าเนื้อหาที่ไม่ซ้ำ และลดหน้าที่ซ้ำกันไม่ให้รวมอยู่ในดัชนีเครื่องมือค้นหา (การรวม สัญญาณการจัดทำดัชนี)

กำหนดพารามิเตอร์ URL ที่จำเป็นสำหรับเครื่องมือค้นหาในการรวบรวมข้อมูลหน้าเนื้อหาแต่ละหน้า (นั่นคือ กำหนดพารามิเตอร์ที่จำเป็นในการสร้างเส้นทางการคลิกอย่างน้อยหนึ่งเส้นทางไปยังแต่ละรายการ) พารามิเตอร์ที่จำเป็นอาจรวมถึง item-id , category-id , หน้า ฯลฯ

พิจารณาว่าพารามิเตอร์ใดจะเป็นประโยชน์ต่อผู้เข้าชมเมื่อมีการสืบค้น และพารามิเตอร์ใดมีแนวโน้มที่จะทำให้เกิดการซ้ำซ้อนในการรวบรวมข้อมูลและการจัดทำดัชนี ในตัวอย่างขนมหวาน (แยมผิวส้ม) พารามิเตอร์ URL "taste" อาจมีประโยชน์สำหรับผู้ใช้ที่มีข้อความค้นหาในตัวอย่าง รส=เปรี้ยว - อย่างไรก็ตาม การพิจารณาพารามิเตอร์ "ราคา" ทำให้เกิดความซ้ำซ้อนโดยไม่จำเป็นก็สมเหตุสมผล Category=gummy-candies&taste=เปรี้ยว& ราคา=เกิน-10 - ตัวอย่างทั่วไปอื่นๆ:

  • พารามิเตอร์ที่มีค่าสำหรับเครื่องมือค้นหา: item-id , category-id , name , brand ...
  • พารามิเตอร์ที่ไม่จำเป็น: session-id , price-range ...
มาดูการใช้ตัวเลือกการกำหนดค่าตัวใดตัวหนึ่งสำหรับ URL ที่มีพารามิเตอร์ที่ไม่จำเป็น เพียงตรวจสอบให้แน่ใจว่าไม่จำเป็นต้องใช้พารามิเตอร์ URL ที่ "ไม่จำเป็น" สำหรับโปรแกรมรวบรวมข้อมูลของเครื่องมือค้นหาในการรวบรวมข้อมูลหรือเพื่อให้ผู้ใช้ค้นหาผลิตภัณฑ์แต่ละรายการ!

ตัวเลือกที่ 1: และลิงก์ภายใน

ทำเครื่องหมาย URL ที่ไม่จำเป็นทั้งหมดด้วยนามสกุล . วิธีนี้จะลดต้นทุนแรงงานของโรบ็อตค้นหาและป้องกันความถี่ในการรวบรวมข้อมูลลดลง คุณต้องจัดการการสแกนทั่วโลกผ่าน robots.txt (หมายเหตุของนักแปล: ดูบทความ " ")
ใช้แอตทริบิวต์ rel="canonical" เพื่อแยกหน้า ดัชนีการค้นหาจากหน้าที่ไม่จำเป็น (เช่น บนหน้า ราคา=5-10 คุณสามารถเพิ่มแอตทริบิวต์ rel="canonical" ซึ่งระบุหมวดหมู่ของแยมผิวส้มทั้งหมด example.com/category.php?category=gummy-candies&taste=sour& หน้า=ทั้งหมด ).

ตัวเลือกที่ 2: Robots.txt และ Disallow

URL ที่มีพารามิเตอร์ที่ไม่จำเป็นจะรวมอยู่ในไดเร็กทอรี /filtering/ ซึ่งจะถูกปิดใน robots.txt (ไม่อนุญาต) วิธีนี้จะช่วยให้เครื่องมือค้นหาทั้งหมดรวบรวมข้อมูลเฉพาะลิงก์ใน (เนื้อหา) ที่ "ถูกต้อง" ของเว็บไซต์ แต่จะบล็อกการรวบรวมข้อมูล URL ที่ไม่ต้องการในครั้งเดียว ตัวอย่างเช่น ( example.com/category.php?category=gummy-candies) หากพารามิเตอร์ที่มีค่าคือรายการ หมวดหมู่ และรสนิยม และตัวระบุเซสชันและราคานั้นไม่จำเป็น ดังนั้น URL สำหรับรสชาติจะเป็นดังนี้:
example.com/category.php?category=gummy-candies& รส=เปรี้ยว, แต่พารามิเตอร์ที่ไม่จำเป็นทั้งหมด เช่น ราคา จะรวมอยู่ใน URL ในไดเร็กทอรีที่กำหนดไว้ล่วงหน้า - /filtering/:
ตัวอย่าง.com /กรอง/ category.php?category=gummy-candies&price=5-10,
ซึ่งจะถูกห้ามผ่าน robots.txt:
ตัวแทนผู้ใช้: *
ไม่อนุญาต: /กรอง/

ตัวเลือกที่ 3: แยกโฮสต์

ตรวจสอบให้แน่ใจ โซลูชั่นที่ดีที่สุดรายการข้างต้น (เช่น สำหรับที่อยู่ที่ไม่จำเป็น) ยังคงมีผลบังคับใช้ มิฉะนั้นเครื่องมือค้นหาได้สร้างลิงก์จำนวนมากในดัชนีแล้ว ดังนั้น งานของคุณจึงมุ่งเป้าไปที่การลดการเติบโตของหน้าที่ไม่จำเป็นซึ่ง Googlebot รวบรวมข้อมูลและรวบรวมสัญญาณการจัดทำดัชนี

ใช้พารามิเตอร์ที่มีการเข้ารหัสมาตรฐานและรูปแบบคีย์=ค่า

ตรวจสอบให้แน่ใจว่าค่าที่ไม่เปลี่ยนเนื้อหาของหน้า เช่น รหัสเซสชัน ถูกนำไปใช้เป็น key=value แทนที่จะเป็นไดเร็กทอรี

ไม่อนุญาตให้คลิกหรือสร้าง URL เมื่อไม่มีองค์ประกอบให้กรอง

เพิ่มตรรกะในการแสดงพารามิเตอร์ URL: ลบพารามิเตอร์ที่ไม่จำเป็นออกแทนที่จะเพิ่มค่าอย่างต่อเนื่อง (เช่น หลีกเลี่ยงการสร้างลิงก์ในลักษณะนี้: example.com/product?cat=gummy-candy&cat=lollipops &cat=gummy-candy&item=swedish-fish).

เก็บพารามิเตอร์ที่มีคุณค่าไว้ใน URL โดยแสดงรายการไว้ก่อน (เนื่องจาก URL ปรากฏในผลการค้นหา) และพารามิเตอร์ที่เกี่ยวข้องน้อยกว่าจะอยู่อันดับสุดท้าย (เช่น รหัสเซสชัน)
หลีกเลี่ยงโครงสร้างลิงก์นี้: example.com/category.php? session-id=123&tracking-id=456&category=gummy-candies&taste=sour
กำหนดค่าพารามิเตอร์ URL ในเครื่องมือของผู้ดูแลเว็บ หากคุณมีความเข้าใจที่ชัดเจนเกี่ยวกับวิธีการทำงานของลิงก์บนไซต์ของคุณ

ตรวจสอบให้แน่ใจว่าเมื่อใช้ JavaScript เพื่อจัดการเนื้อหาแบบไดนามิก (จัดเรียง/กรอง/ซ่อน) โดยไม่ต้องอัปเดต URL มีที่อยู่เว็บจริงบนไซต์ของคุณที่มีมูลค่าการค้นหา เช่น หมวดหมู่หลักและหน้าผลิตภัณฑ์ ที่สามารถรวบรวมข้อมูลและจัดทำดัชนีได้ พยายามอย่าใช้อย่างเดียว หน้าแรก(เช่น URL เดียว) สำหรับทั้งไซต์ของคุณ และใช้ JavaScript เพื่อเปลี่ยนแปลงเนื้อหาด้วยการนำทางแบบไดนามิก แต่น่าเสียดายที่ผู้ใช้จะมี URL เดียวในการค้นหา นอกจากนี้ ให้ตรวจสอบว่าไม่มีผลกระทบต่อประสิทธิภาพในการกรองแบบไดนามิก ด้านที่เลวร้ายที่สุดเนื่องจากจะป้องกันไม่ให้ผู้ใช้ทำงานกับไซต์

ปรับปรุงการจัดทำดัชนีหน้าต่างๆ ของเนื้อหาเดียวกันโดยการระบุแอตทริบิวต์ rel="canonical" บนหน้าเวอร์ชันสิทธิพิเศษ แอตทริบิวต์ rel="canonical" สามารถใช้ได้ภายในโดเมนตั้งแต่ 1 โดเมนขึ้นไป

เพิ่มประสิทธิภาพการจัดทำดัชนีเนื้อหาที่มีการแบ่งหน้า (เช่น page=1 และ page=2 จากหมวดหมู่ "gummy candy") โดยวิธีใดวิธีหนึ่งต่อไปนี้

  • เพิ่มแอตทริบิวต์ rel="canonical" ลงในชุดหน้าเว็บที่ระบุหมวดหมู่ Canonical ด้วยพารามิเตอร์ "view-all" (เช่น page=1, page=2 และ page=3 จากหมวดหมู่ "gummy candies" พร้อมด้วย with rel=”canonical” บน Category=gummy-candies&page=all) ตรวจสอบให้แน่ใจว่าหน้าเว็บมีความเกี่ยวข้องกับผู้ใช้และโหลดได้รวดเร็ว
  • ใช้มาร์กอัปการแบ่งหน้า rel="next" และ rel="prev" เพื่อระบุความสัมพันธ์ระหว่างแต่ละหน้า (ดู "การแบ่งหน้าด้วย rel="next" และ rel="prev" ")
รวมเฉพาะลิงก์ Canonical ในแผนผังไซต์ของคุณ

สำหรับแต่ละโพสต์และ โพสต์เวิร์ดเพรสผู้ใช้สามารถระบุส่วนหัว (หมวดหมู่) หนึ่งรายการขึ้นไป คุณลักษณะนี้ช่วยให้คุณสามารถจัดกลุ่มโพสต์ที่มีความหมายคล้ายกัน และเปิดโอกาสให้ผู้เยี่ยมชมได้อ่านและดูเฉพาะส่วนที่พวกเขาชอบ ตัวอย่างเช่น เมื่อฉันสร้างบล็อกหลักของฉัน Tod’s Blog ฉันจะเขียนเกี่ยวกับความแตกต่างทั้งหมดของอินเทอร์เน็ต ตั้งแต่การออกแบบไปจนถึงการเขียนโปรแกรม สมมติว่าบุคคลหนึ่งมาจากเครื่องมือค้นหาไปยังบทความเกี่ยวกับ Wordpress และต้องการอ่านเพิ่มเติมเกี่ยวกับระบบ - เขาจะต้องค้นหาในเอกสารสำคัญ ใช้การค้นหาซ้ำ หรือดูโพสต์ทั้งหมดติดต่อกัน แน่นอนว่าทั้งหมดนี้สามารถหลีกเลี่ยงได้โดยไปที่หมวดหมู่พิเศษที่เรียกว่า WordPress หรือตัวอย่างเช่น สำหรับผู้ที่สนใจเฉพาะเรื่องการออกแบบ ส่วนของบล็อกก็อาจเป็นที่สนใจ

หากคุณดูส่วนหัวของบล็อกอย่างใกล้ชิด คุณจะเห็นเมนูประเภทต่างๆ หมวดหมู่เวิร์ดเพรสทำหน้าที่เป็นส่วนของโครงการ สำหรับฉัน นี่เป็นวิธีที่ค่อนข้างสะดวกและชัดเจนในการแยกหัวข้อของรายการ

ที่กึ่งกลางของหน้า คุณจะเห็นแบบฟอร์มสำหรับเพิ่มหมวดหมู่ใหม่ ที่นี่คุณจะต้องระบุชื่อ (ชื่อ) ป้ายกำกับ (ส่วนหนึ่ง ลิงก์ URLสำหรับ CNC) หมวดหมู่หลัก (ถ้ามี) และคุณยังสามารถตั้งค่าได้อีกด้วย คำอธิบายสั้น ๆ- หมวดหมู่หลักช่วยให้คุณสร้างส่วนใน WordPress ที่มีการซ้อนหลายระดับ - ตัวอย่างเช่นสำหรับหมวดหมู่ "WordPress" ในบล็อกไอทีบางบล็อก คุณสามารถเพิ่มเทมเพลต ปลั๊กอิน ฯลฯ เดียวกันได้

ที่ด้านขวาของหน้าหมวดหมู่ หมวดหมู่ WordPress ทั้งหมดจะแสดงขึ้น โดยสามารถแก้ไขหรือลบได้ หากต้องการดำเนินการ เพียงเลื่อนเคอร์เซอร์ของเมาส์ไปที่ชื่อหมวดหมู่ใดหมวดหมู่หนึ่ง หลังจากนั้นคุณจะเห็นเมนูป๊อปอัปขนาดเล็ก

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

ที่นี่คุณสามารถเพิ่มหมวดหมู่ใหม่ได้โดยคลิกลิงก์ที่เหมาะสม ข้อเสียเปรียบเพียงอย่างเดียวของกลไกนี้คือเมื่อสร้างคุณสามารถระบุได้เฉพาะชื่อและหมวดหมู่หลักเท่านั้นในขณะที่ตั้งค่าฟิลด์ป้ายกำกับคุณจะต้องไปที่ส่วน "หมวดหมู่" และแก้ไขข้อมูลที่นั่น

นอกจากนี้ คุณสามารถแก้ไขหมวดหมู่สำหรับโพสต์บนบล็อกผ่านรายการในเมนูโพสต์ - แก้ไข ที่นั่นเมื่อคุณวางเมาส์เหนือสิ่งพิมพ์ใดสิ่งพิมพ์หนึ่ง คุณจะเห็นลิงก์ “ แก้ไขด่วน- คลิกที่มันและดูแบบฟอร์มสำหรับการแก้ไข:

ที่นี่คุณสามารถเปลี่ยนหมวดหมู่ แท็ก และข้อมูลเพิ่มเติมทั้งหมดในบทความได้ สะดวกมาก + ใช้งานได้โดยไม่ต้องโหลดหน้าซ้ำ

ฟังก์ชัน wp_list_categories สำหรับหมวดหมู่ WordPress

ตามเนื้อผ้าฉันพิจารณาไม่เพียงแต่ปัญหาในการทำงานกับองค์ประกอบบางอย่างของระบบเท่านั้น แต่ยังให้ฟังก์ชันพิเศษสำหรับเทมเพลตด้วย เหมือนที่ผมพูดถึงเลย ดังนั้นหากต้องการแสดงรายการหมวดหมู่พร้อมลิงก์ให้ใช้ wp_list_categories- มีข้อโต้แย้งหลายประการ:

  • show_option_all - แสดงลิงก์ไปยังทุกหมวดหมู่หากคุณเลือกรายการเป็นสไตล์การแสดงผล
  • orderby – จัดเรียงหมวดหมู่ตาม ID ชื่อ (ชื่อ) ป้ายกำกับ (กระสุน) จำนวนโพสต์ (นับ)
  • ลำดับ – ลำดับการจัดเรียง (ASC – เพิ่มขึ้น, DESC – ลดลง)
  • show_last_updated - แสดงวันที่อัปเดตครั้งล่าสุด
  • สไตล์ – สไตล์การออกแบบ: รายการ, การแบ่งผ่าน
    (ไม่มี).
  • show_count – แสดงจำนวนโพสต์ในหมวดหมู่
  • Hide_empty – ซ่อนหมวดหมู่ว่างโดยไม่มีการโพสต์
  • use_desc_for_title – ใช้คำอธิบายสำหรับแอตทริบิวต์ชื่อในลิงก์
  • child_of – แสดงเฉพาะหมวดหมู่สำหรับหมวดหมู่หลักที่กำหนด
  • ฟีด – แสดงลิงก์ไปยังฟีดสำหรับหมวดหมู่
  • feed_type – ประเภทฟีด
  • feed_image – รูปภาพสำหรับไอคอน RSS
  • รวม – แยกหมวดหมู่ออกจากรายการ และพารามิเตอร์ child_of จะถูกปิดใช้งานโดยอัตโนมัติ
  • ไม่รวมต้นไม้ - ไม่รวมสาขาหมวดหมู่ทั้งหมด
  • include คือพารามิเตอร์ผกผันที่รวมเฉพาะหมวดหมู่ WordPress ที่ระบุในรายการ
  • ลำดับชั้น – พารามิเตอร์สำหรับการแสดงหมวดหมู่ย่อย
  • title_li – ชื่อของรายการหมวดหมู่
  • number – จำนวนหมวดหมู่ที่จะแสดง (หากมีมากเกินไป)
  • echo – แสดงหมวดหมู่ ค่าเริ่มต้นเป็น True
  • ความลึก – ระบุจำนวนระดับสำหรับหมวดหมู่ย่อยที่จะแสดง

สุดท้ายนี้ ฉันจะยกตัวอย่างการใช้ wp_list_categories หลายๆ ตัวอย่าง ประการแรก ตัวเลือกจากส่วนหัวของบล็อกนี้

"hide_empty=1&exclude=1&title_li=&orderby=count&order=desc&use_desc_for_title=0") ; ?>

ที่นี่มันถูกตั้งค่าให้แสดงหมวดหมู่ที่ซ่อนอยู่ แยกหมวดหมู่ออกจากรายการ บรรทัดว่างสำหรับชื่อบล็อก เรียงลำดับตามจำนวนบทความ และตามลำดับจากลดลง (นั่นคือ ฉันมีบทความมากที่สุดในส่วนนี้) อาร์กิวเมนต์สุดท้ายไม่ได้แทนที่คำอธิบายหมวดหมู่ในชื่อเรื่องของลิงก์

และอีกสองสามสถานการณ์ง่ายๆ การใช้การยกเว้นและการรวมหมวดหมู่

หากคุณมีอะไรจะเพิ่มเกี่ยวกับส่วนหัวและหมวดหมู่ของ WordPress โปรดเขียนความคิดเห็น

อัปเดต:คุณอาจต้องใช้แฮ็กเล็กๆ เพื่อ ตามค่าเริ่มต้นใน WordPress ข้อความชื่อเรื่องจะถูกกำหนดไว้เช่น "ดูรายการทั้งหมดในหมวดหมู่ ... " คุณสามารถปล่อยชื่อเรื่องของหมวดหมู่แทนได้ - อ่านบทความที่ลิงก์ด้านบน

ส่งกลับอาร์เรย์ของวัตถุที่มีข้อมูลเกี่ยวกับหมวดหมู่

พารามิเตอร์ที่ส่งไปยังฟังก์ชันนี้จะคล้ายกับพารามิเตอร์ที่ส่งไปยังฟังก์ชันนี้มาก wp_list_categories()และสามารถส่งผ่านได้ทั้งแบบอาร์เรย์หรือสตริงการสืบค้น: type=post&order=DESC

✈ 1 ครั้ง = 0.005625s = ช้ามาก- 50,000 ครั้ง = 11.98 วินาที = ช้า- PHP 7.1.11, WP 4.9.5

การใช้งาน

$categories = get_categories($args);

รูปแบบการใช้งาน

$categories = get_categories(array("taxonomy" => "category", "type" => "post", "child_of" => 0, "parent" => "", "orderby" => "name", " order" => "ASC", "hide_empty" => 1, "ลำดับชั้น" => 1, "ไม่รวม" => "", "รวม" => "", "number" => 0, "pad_counts" => เท็จ, // รายการทั้งหมดสำหรับพารามิเตอร์โปรดดูคำอธิบายฟังก์ชัน http://wp-kama.ru/function/get_terms)); if($categories)( foreach($categories as $cat)( // ข้อมูลใน $cat object // $cat->term_id // $cat->name (Rubric 1) // $cat->slug (rubrika - 1) // $cat->term_group (0) // $cat->term_taxonomy_id (4) // $cat->taxonomy (หมวดหมู่) // $cat->คำอธิบาย (ข้อความคำอธิบาย) // $cat-> ผู้ปกครอง (0) // $cat->จำนวน (14) // $cat->object_id (2743) // $cat->cat_ID (4) // $cat->category_count (14) // $cat-> category_description (ข้อความคำอธิบาย) // $cat->cat_name (Rubric 1) // $cat->category_nicename (rubrika-1) // $cat->category_parent (0) ) ) อนุกรมวิธาน (เส้น)ชื่อของอนุกรมวิธานที่จะประมวลผล เพิ่มตั้งแต่เวอร์ชัน 3.0
ค่าเริ่มต้น: "หมวดหมู่"พิมพ์ (เส้น)
  • โพสต์ - หมวดหมู่สำหรับการโพสต์ (ค่าเริ่มต้น);
  • ลิงค์ - ส่วนลิงค์
    ค่าเริ่มต้น: "โพสต์"
เด็ก_ของ (เส้น)รับหมวดหมู่ย่อย (รวมถึงระดับการซ้อนทั้งหมด) ของหมวดหมู่ที่ระบุ พารามิเตอร์ระบุ ID ของหมวดหมู่หลัก (หมวดหมู่ที่มีหมวดหมู่ซ้อนที่คุณต้องการแสดง) พ่อแม่(ตัวเลข)
รับหมวดหมู่ที่มีหมวดหมู่หลักเท่ากับ ID ที่ระบุในพารามิเตอร์ ความแตกต่างจาก child_of คือการแสดงการซ้อนระดับหนึ่งค่าเริ่มต้น: "" (เส้น)

สั่งซื้อโดย

  • จัดเรียงข้อมูลที่ได้รับตามเกณฑ์ที่กำหนด เช่นตามจำนวนโพสต์ในแต่ละหมวดหมู่หรือตามชื่อหมวดหมู่ มีเกณฑ์ดังต่อไปนี้:
  • ID - จัดเรียงตาม ID;
  • ชื่อ - จัดเรียงตามชื่อ (ค่าเริ่มต้น);
  • ทาก - จัดเรียงตาม alt ชื่อ (ทาก);
  • นับ - ตามจำนวนรายการในหมวดหมู่

term_group - ตามกลุ่ม

ค่าเริ่มต้น: "ชื่อ" (เส้น)

คำสั่ง

  • ทิศทางการเรียงลำดับที่ระบุในพารามิเตอร์ "orderby":
  • ASC - ตามลำดับจากเล็กไปใหญ่ที่สุด (1, 2, 3; a, b, c); DESC-ในลำดับย้อนกลับ

จากใหญ่ไปเล็กที่สุด (3, 2, 1; c, b, a)

ค่าเริ่มต้น: "ASC" Hide_empty

(ตรรกะ)

  • ไม่ว่าจะได้รับหมวดหมู่ว่างหรือไม่ (ไม่มีรายการ):
  • 1 (จริง) - อย่ารับอันว่าง

0 (เท็จ) - รับค่าว่าง

ค่าเริ่มต้น: จริง Hide_emptyลำดับชั้น หากตั้งค่าพารามิเตอร์เป็นจริง
0 (เท็จ) - รับค่าว่างจากนั้นผลลัพธ์จะรวมหมวดหมู่ย่อยที่ว่างเปล่าซึ่งหมวดหมู่ย่อยมีรายการ (ไม่ว่างเปล่า) ยกเว้น(สตริง/อาร์เรย์)
รับหมวดหมู่ที่มีหมวดหมู่หลักเท่ากับ ID ที่ระบุในพารามิเตอร์ ความแตกต่างจาก child_of คือการแสดงการซ้อนระดับหนึ่งยกเว้นหมวดหมู่ใดๆ ออกจากรายการ คุณต้องระบุ ID หมวดหมู่โดยคั่นด้วยเครื่องหมายจุลภาคหรือในอาร์เรย์ หากระบุพารามิเตอร์นี้ พารามิเตอร์ child_of จะถูกแทนที่ ยกเว้นรวม
รับหมวดหมู่ที่มีหมวดหมู่หลักเท่ากับ ID ที่ระบุในพารามิเตอร์ ความแตกต่างจาก child_of คือการแสดงการซ้อนระดับหนึ่งแสดงรายการเฉพาะหมวดหมู่ที่ระบุ คุณต้องระบุรหัสหมวดหมู่โดยคั่นด้วยเครื่องหมายจุลภาคหรือในอาร์เรย์ พ่อแม่ขีดจำกัด จำนวนหมวดหมู่ที่จะถูกดึงข้อมูล ตามค่าเริ่มต้น ไม่มีข้อจำกัด - หมวดหมู่ทั้งหมดจะถูกดึงข้อมูล Hide_empty pad_counts
หากคุณผ่าน True ตัวเลขที่แสดงจำนวนโพสต์ในหมวดหมู่หลักจะเท่ากับผลรวมของโพสต์และโพสต์จากหมวดหมู่ย่อย

ค่าเริ่มต้น: เท็จ

ตัวอย่าง

#1 รายการแบบเลื่อนลง

ในการสร้างรายการหมวดหมู่แบบเลื่อนลง เราสามารถใช้ฟังก์ชันพิเศษอื่นเพื่อจุดประสงค์นี้ได้ wp_dropdown_categories() :

Wp_dropdown_categories(array("hide_empty" => 0, "name" => "category_parent", "orderby" => "name", "selected" => $category->parent, "hierarchical" => true, "show_option_none" => __("ไม่มี")));

อย่างไรก็ตาม ด้วยวิธีนี้ เราจะสูญเสียความยืดหยุ่นในการตั้งค่ารายการ เนื่องจากเราจะได้รับรายการที่มีรูปแบบครบถ้วน ดังนั้นในบางกรณี การสร้างรายการแบบเลื่อนลงโดยใช้ฟังก์ชันจะมีเหตุผลมากกว่า get_categories()

"; echo $option; ) ?>

#2 รายการหมวดหมู่และคำอธิบาย

ตัวอย่างนี้จะแสดงให้เราเห็นว่าเราสามารถแสดงรายการลิงก์ไปยังหมวดหมู่ได้อย่างไร โดยทันทีหลังจากแต่ละลิงก์จะมีคำอธิบายของหมวดหมู่ (ระบุเมื่อสร้าง/แก้ไขหมวดหมู่):

"ชื่อ", "คำสั่งซื้อ" => "ASC"); foreach($หมวดหมู่เป็น $หมวดหมู่)( echo " หมวดหมู่:

term_id) "" ชื่อ = "" . sprintf(__("ดูโพสต์ทั้งหมดใน %s"), $category->ชื่อ) "" " . ">" . $category->ชื่อ"

"; เอคโค่"

คำอธิบาย:". $category->description . "

"; เอคโค่"

"; } ?>

จำนวนการโพสต์: ". $category->count "

  • หมายเหตุ

โปรดดูที่ get_terms() ประเภทของอาร์กิวเมนต์ที่สามารถเปลี่ยนแปลงได้

รายการการเปลี่ยนแปลง จากเวอร์ชัน 2.1.0

แนะนำตัว. รหัส รับหมวดหมู่: wp-รวม/category.php

WP5.3.2 "หมวดหมู่"); $args = wp_parse_args($args, $defaults);", "/** * กรองอนุกรมวิธานที่ใช้ในการดึงคำศัพท์เมื่อเรียก get_categories()")); $args["taxonomy"] = "link_category"; ) $categories = get_terms($args); if (is_wp_error($categories)) ( $categories = array(); ) else ( $categories = (array) ) $categories; foreach (array_keys($categories) เป็น $k) ( _make_cat_compat($categories[ $k ]); ) ) ส่งคืน $categories;

ฉันเริ่มเขียนชั้นเรียนที่จะใช้แนวคิดที่ระบุไว้ในนั้น
แม่นยำยิ่งขึ้นเนื่องจากฟังก์ชันหลักถูกใช้ภายในกรอบงานของกรอบการทำงานแล้ว ฉันจึงเริ่มแยกมันออกเป็นคลาสอื่น ฉันอยากจะใช้โอกาสนี้ขอบคุณสมาชิก PHPClub สำหรับความช่วยเหลือในการแก้ไขข้อผิดพลาดที่สำคัญและความคิดเห็นที่เป็นประโยชน์ ด้านล่างนี้ฉันจะพยายามอธิบายคุณสมบัติหลัก แต่ก่อนอื่นเล็กน้อย

ข้อจำกัดความรับผิดชอบ

มีหลายวิธีในการทำงานกับ SQL - คุณสามารถใช้ตัวสร้างคิวรี คุณสามารถใช้ ORM คุณสามารถทำงานกับ SQL ล้วนๆ ได้ ฉันเลือกตัวเลือกสุดท้ายเพราะอยู่ใกล้ฉันมากขึ้น ผมว่าสองอันแรกก็ไม่ได้แย่เลย เพียงแต่โดยส่วนตัวแล้วฉันรู้สึกคับแคบภายในกรอบการทำงานของพวกเขามาโดยตลอด แต่ฉันไม่เคยอ้างว่าเวอร์ชันของฉันดีกว่าเลย มันเป็นเพียงอีกทางเลือกหนึ่ง ซึ่งสามารถนำมาใช้เหนือสิ่งอื่นใดเมื่อเขียน ORM ไม่ว่าในกรณีใด ฉันเชื่อว่าการมีวิธีที่ปลอดภัยในการทำงานกับ SQL ล้วนๆ จะไม่ส่งผลเสียใดๆ แต่ในขณะเดียวกัน อาจช่วยให้กลุ่มสุดท้ายที่เหลือที่ใช้ mysql_* ในโค้ดของแอปพลิเคชันสามารถละทิ้งแนวปฏิบัติที่ไม่ดีนี้ได้ในที่สุด


โดยสรุป คลาสนี้สร้างขึ้นจากชุดฟังก์ชันตัวช่วยที่ช่วยให้คุณสามารถดำเนินการกับฐานข้อมูลส่วนใหญ่ได้ในบรรทัดเดียว ในขณะที่ให้บริการ (ต่างจาก API มาตรฐาน) เต็มการป้องกันการฉีด SQL ใช้งานโดยใช้ชุดตัวยึดตำแหน่งเพิ่มเติมที่ปกป้องข้อมูลประเภทใด ๆ ที่อาจอยู่ภายใต้การร้องขอ
ชั้นเรียนมีหลักการพื้นฐานสามประการ:
  1. ป้องกันการฉีด SQL ได้ 100%
  2. ในขณะเดียวกันการป้องกันก็ใช้งานได้สะดวกมากทำให้โค้ดสั้นลงแทนที่จะยาวขึ้น
  3. ความคล่องตัว พกพาสะดวก และง่ายต่อการเรียนรู้
ฉันจะกล่าวถึงรายละเอียดเพิ่มเติมเล็กน้อยในแต่ละประเด็น

ความปลอดภัย

ได้รับการรับรองตามกฎสองข้อที่ฉันกำหนดไว้ในบทความ:
  1. ใดๆ- ไม่มีข้อยกเว้น! - องค์ประกอบไดนามิกจะรวมอยู่ในคำขอ เท่านั้นผ่านตัวยึดตำแหน่ง
  2. ทุกอย่างที่ไม่สามารถทดแทนได้โดยใช้ตัวยึดตำแหน่งจะต้องดำเนินการผ่านรายการสีขาวก่อน
น่าเสียดายที่ไลบรารีมาตรฐานไม่ได้ให้การป้องกันที่สมบูรณ์ต่อการแทรก โดยปกป้องเฉพาะสตริงและตัวเลขโดยใช้คำสั่งที่เตรียมไว้
ดังนั้น เพื่อให้การป้องกันเสร็จสมบูรณ์ เราต้องละทิ้งแนวคิดที่จำกัดอย่างเห็นได้ชัดของข้อความที่เตรียมไว้ หันไปใช้แนวคิดที่กว้างขึ้น นั่นก็คือตัวยึดตำแหน่ง ยิ่งไปกว่านั้น ตัวยึดตำแหน่งที่พิมพ์ (เราทุกคนรู้จักสิ่งนี้จากฟังก์ชันตระกูล printf(): %d คือตัวยึดตำแหน่งที่บอก parser วิธีการประมวลผลค่าที่ถูกแทนที่ ในกรณีนี้ - เป็นจำนวนเต็ม) นวัตกรรมนี้ประสบความสำเร็จอย่างมากจนสามารถแก้ไขปัญหามากมายได้ทันทีและทำให้โค้ดง่ายขึ้นอย่างมาก ฉันจะเขียนเพิ่มเติมเกี่ยวกับตัวยึดตำแหน่งที่พิมพ์ด้านล่าง
การสนับสนุนสำหรับการกรองตามรายการขาวนั้นมาจากสองฟังก์ชันซึ่งค่อนข้างเข้าใจยาก แต่ก็ยังจำเป็น

ความสะดวกและความสั้นของรหัสแอปพลิเคชัน

ที่นี่ ตัวยึดตำแหน่งที่พิมพ์ยังช่วยฉันได้มาก ซึ่งทำให้ฉันสามารถเรียกใช้ฟังก์ชันบรรทัดเดียว โดยส่งทั้งคำขอและข้อมูลในครั้งเดียว พร้อมชุดตัวช่วยที่ชวนให้นึกถึง PEAR::DB - ฟังก์ชันที่ส่งคืนผลลัพธ์ประเภทที่ต้องการทันที ผู้ช่วยทั้งหมดได้รับการจัดระเบียบตามรูปแบบเดียวกัน: พารามิเตอร์บังคับหนึ่งรายการจะถูกส่งผ่านไปยังฟังก์ชัน - คำขอที่มีตัวยึดตำแหน่งและพารามิเตอร์ทางเลือกได้มากเท่าที่ต้องการ จำนวนและลำดับที่ต้องตรงกับหมายเลขและลำดับของตัวยึดตำแหน่งในคำขอ . ฟังก์ชั่นของตระกูล Ind ใช้พารามิเตอร์ที่จำเป็นอีกหนึ่งพารามิเตอร์ - ชื่อของฟิลด์ที่ใช้จัดทำดัชนีอาร์เรย์ที่ส่งคืน
จากประสบการณ์ของฉัน ฉันมาถึงชุดค่าส่งคืนต่อไปนี้ (และเป็นผลให้เป็นผู้ช่วยเหลือ):
  • query() - ส่งคืนทรัพยากร mysqli สามารถใช้แบบดั้งเดิมได้ด้วยการ fetch() ฯลฯ
  • getOne() - ส่งกลับค่าสเกลาร์ ซึ่งเป็นองค์ประกอบแรกของแถวแรกของผลลัพธ์
  • getRow() - อาร์เรย์หนึ่งมิติ ซึ่งเป็นแถวแรกของผลลัพธ์
  • getCol() - อาร์เรย์สเกลาร์หนึ่งมิติ - คอลัมน์ตาราง
  • getAll() - อาร์เรย์สองมิติจัดทำดัชนีตามตัวเลขตามลำดับ
  • getInd() - อาร์เรย์สองมิติที่จัดทำดัชนีโดยค่าของฟิลด์ที่ระบุโดยพารามิเตอร์แรก
  • getIndCol() คืออาร์เรย์ของสเกลาร์ที่จัดทำดัชนีโดยฟิลด์จากพารามิเตอร์แรก สิ่งที่ขาดไม่ได้ในการรวบรวมพจนานุกรมเช่นคีย์ => ค่า
เป็นผลให้การเรียกฐานข้อมูลส่วนใหญ่ลดลงเหลือหนึ่งหรือสองบรรทัด (แทนที่จะเป็น 5-10 ด้วยวิธีดั้งเดิม):
$data = $db->getAll("SELECT * FROM ?n WHERE mod=?s LIMIT ?i",$table,$mod,$limit);
รหัสนี้มีเพียงองค์ประกอบที่จำเป็นและมีความหมายเท่านั้น แต่ไม่มีสิ่งใดที่ไม่จำเป็นและซ้ำซ้อน เครื่องในทั้งหมดถูกซ่อนไว้อย่างเรียบร้อยภายในคลาส: ตัวช่วย getAll() ช่วยให้คุณได้ผลลัพธ์ที่ต้องการทันทีโดยไม่ต้องเขียนลูปในโค้ดของแอปพลิเคชัน และตัวยึดตำแหน่งที่พิมพ์อนุญาต ได้อย่างปลอดภัยเพิ่มองค์ประกอบแบบไดนามิกให้กับคำขอ ใดๆประเภทโดยไม่ต้องระบุการเชื่อมโยงด้วยตนเอง (bind_param) รหัส DRY พิเศษ! ในกรณีที่ใช้ตัวยึดตำแหน่ง ?a และ ?u จำนวนโค้ดจะต่างกันมากขึ้น:
$data = $db->getAll("SELECT * FROM table WHERE category IN (?a)",$ids);

ความเก่งกาจและง่ายต่อการเรียนรู้

ยืนบนเสาสามเสา:
  1. มาก API ขนาดเล็ก - ตัวยึดตำแหน่งครึ่งโหลและผู้ช่วยเหลือจำนวนเท่ากัน
  2. เราทำงานร่วมกับ SQL แบบเก่าที่ดี ซึ่งไม่จำเป็นต้องเรียนรู้ใหม่
  3. ฟังก์ชัน parse() ดูเหมือนไม่มีใครสังเกตเห็นแต่มีประโยชน์อย่างเหลือเชื่อ เดิมทีมีจุดประสงค์เพื่อการดีบักเท่านั้น แต่ในที่สุดก็กลายเป็นองค์ประกอบสำคัญเมื่อเขียนคำสั่งที่ซับซ้อน
เป็นผลให้คำถามที่ซับซ้อนทั้งหมดถูกรวบรวมด้วยวิธีที่ล้าสมัย - ตัวอย่างเช่นในวง - แต่ในขณะเดียวกันก็เป็นไปตามกฎความปลอดภัยทั้งหมด!
ฉันขอยกตัวอย่างเล็ก ๆ ให้คุณ (ดูตัวอย่างที่ซับซ้อนกว่านี้ได้ในเอกสารประกอบที่ลิงค์ที่ด้านล่างของบทความ):
กรณีที่พบบ่อยเมื่อเราต้องการเพิ่มเงื่อนไขให้กับแบบสอบถามหากมีตัวแปร

$sqlpart = ""; if (!empty($var)) ( $sqlpart = $db->parse(" AND field = ?s", $var); ) $data = $db->getAll("SELECT * FROM table WHERE a=? ฉัน ?p", $id, $sqlpart);
สิ่งสำคัญคือต้องทราบบางสิ่งที่นี่
ประการแรก เนื่องจากเราไม่ได้ผูกมัดกับ API ดั้งเดิม จึงไม่มีใครห้ามไม่ให้เราแยกวิเคราะห์คำขอทั้งหมด แต่เพียงบางส่วนเท่านั้น สิ่งนี้กลายเป็นความสะดวกอย่างยิ่งสำหรับการสืบค้นที่รวบรวมตามตรรกะบางประการ: เราแยกวิเคราะห์คำขอเพียงบางส่วนเท่านั้น จากนั้นจึงแทนที่เป็นคำขอหลักผ่านตัวยึดตำแหน่ง "ไม่ได้ใช้งาน" พิเศษเพื่อหลีกเลี่ยงการแยกวิเคราะห์ซ้ำ (และเพื่อให้เป็นไปตามข้อกำหนด) ด้วยกฎที่ว่า “องค์ประกอบใดๆ จะถูกแทนที่ผ่านตัวยึดตำแหน่งเท่านั้น")
แต่น่าเสียดายที่นี่คือจุดอ่อนของทั้งชั้นเรียน แตกต่างจากตัวยึดตำแหน่งอื่นๆ ทั้งหมด (ซึ่งถึงแม้จะใช้ไม่ถูกต้อง แต่ก็ไม่เคยนำไปสู่การแทรก) การใช้ตัวยึดตำแหน่งอย่างไม่ถูกต้อง?p สามารถนำไปสู่สิ่งนี้ได้
อย่างไรก็ตาม การป้องกันความผิดพลาดจะทำให้คลาสมีความซับซ้อนอย่างมาก แต่ก็ยังไม่สามารถป้องกันการแทรกตัวแปรโง่ ๆ ลงในสตริงการสืบค้นได้ ฉันจึงตัดสินใจทิ้งมันไว้เหมือนเดิม แต่ถ้าคุณรู้วิธีในการแก้ปัญหานี้โดยไม่ต้องออกแบบมากเกินไป ฉันจะขอบคุณสำหรับแนวคิดต่างๆ

อย่างไรก็ตาม ในท้ายที่สุด เราก็มีเครื่องมือสร้างคิวรีที่ทรงพลังและใช้งานง่ายซึ่งมากกว่าการพิสูจน์ข้อเสียเล็กๆ น้อยๆ นี้
มีประสิทธิภาพเนื่องจากเราไม่ได้จำกัดอยู่เพียงไวยากรณ์ของตัวสร้างคิวรี “SQL ที่เขียนด้วย PHP” - เราเขียน SQL ล้วนๆ
ง่ายเพราะ API การสร้างแบบสอบถามทั้งหมดประกอบด้วยตัวยึดตำแหน่งครึ่งโหลและฟังก์ชัน parse()
นี่คือตัวอย่างที่ฉันชอบ - แทรกโดยใช้ฟังก์ชัน Mysql
$data = array("field"=>$value,"field2"=>$value); $sql = "ใส่ลงในตาราง SET ts=unix_timestamp(), ip=inet_aton(?s),?u"; $db->query($sql, $ip, $data);
ในด้านหนึ่ง เรารักษาไวยากรณ์ SQL ไว้ อีกด้านหนึ่ง ทำให้ปลอดภัย และประการที่สาม เราลดจำนวนโค้ดลงอย่างมาก

ข้อมูลเพิ่มเติมเกี่ยวกับตัวยึดตำแหน่งที่พิมพ์

ก่อนอื่น เรามาตอบคำถามว่าทำไมต้องมีตัวยึดตำแหน่งเลย?
โดยทั่วไปแล้วนี่เป็นสถานที่ธรรมดาอยู่แล้ว แต่อย่างไรก็ตามฉันขอย้ำอีกครั้ง - ข้อมูลไดนามิกใดๆ ควรรวมอยู่ในคำขอผ่านตัวยึดตำแหน่งเท่านั้นด้วยเหตุผลดังต่อไปนี้:
  • สิ่งที่สำคัญที่สุดคือความปลอดภัย การเพิ่มตัวแปรผ่านตัวยึดตำแหน่งทำให้เรามั่นใจได้ว่าจะมีการจัดรูปแบบอย่างถูกต้อง
  • การจัดรูปแบบท้องถิ่น นี่เป็นจุดสำคัญไม่แพ้กัน ประการแรก ข้อมูลจะถูกจัดรูปแบบทันทีก่อนป้อนคำขอ และไม่ส่งผลกระทบต่อตัวแปรดั้งเดิม ซึ่งจากนั้นจึงนำไปใช้ที่อื่นได้ ประการที่สอง ข้อมูลจะถูกจัดรูปแบบตามที่จำเป็น ไม่ใช่ก่อนที่สคริปต์จะเริ่มทำงาน เช่นเดียวกับเครื่องหมายคำพูดวิเศษ และนักพัฒนาหลายคนไม่ได้อยู่ในตำแหน่งที่เป็นไปได้สิบตำแหน่งในโค้ด ซึ่งแต่ละคนสามารถพึ่งพากันและกันได้
การพัฒนาแนวคิดนี้ต่อไปเรามาถึงแนวคิดที่ว่าเครื่องกระตุ้นหัวใจต้องเป็น พิมพ์แล้ว- แต่ทำไม?
ที่นี่ฉันอยากจะหยุดสักครู่และติดตามประวัติความเป็นมาของการพัฒนาความคิดของโปรแกรมเมอร์ในด้านการป้องกันการฉีด
ในตอนแรกมีความโกลาหล - ไม่มีการป้องกันเลยเราผลักทุกอย่างเหมือนเดิม
จากนั้นมันก็ไม่ได้ดีไปกว่านี้อีกแล้ว ด้วยกระบวนทัศน์ “มากู้คืนทุกสิ่งที่เข้ามาในสคริปต์จากผู้ใช้กันเถอะ” และจุดสุดยอดในรูปแบบของคำพูดวิเศษ
จากนั้นผู้มีความคิดที่ดีที่สุดก็สรุปว่าถูกต้องที่จะไม่พูดถึงการคัดกรอง แต่เกี่ยวกับการจัดรูปแบบ เนื่องจากการจัดรูปแบบไม่ได้มีเพียงเค้าโครงเดียวเสมอไป นี่คือลักษณะที่เมธอด quote() ปรากฏใน PDO ซึ่งจัดรูปแบบสตริงเสร็จสมบูรณ์ - ไม่เพียงแต่ใช้อักขระพิเศษในนั้นเท่านั้น แต่ยังรวมไว้ในเครื่องหมายคำพูดด้วย โดยไม่ต้องอาศัยโปรแกรมเมอร์ เป็นผลให้แม้ว่าโปรแกรมเมอร์จะใช้ฟังก์ชั่นนี้ในตำแหน่งที่ไม่ถูกต้อง (เช่นสำหรับตัวเลข) การฉีดยังคงไม่ทำงาน (และในกรณีของการหลบหนีเปล่าผ่าน mysql_real_escape_string มันจะผ่านไปอย่างง่ายดายถ้าเราใส่ตัวเลขเข้าไป ข้อความค้นหาโดยไม่ใส่เครื่องหมายคำพูด ) เมื่อใช้ในการจัดรูปแบบตัวระบุ ฟังก์ชันนี้จะทำให้เกิดข้อผิดพลาดในขั้นตอนการพัฒนา ซึ่งแนะนำให้ผู้เขียนโค้ดทราบว่าเขาคิดผิดเล็กน้อย
น่าเสียดายที่ผู้เขียน PDO หยุดอยู่ตรงนั้น เนื่องจากแนวคิดที่ว่ามีเพียงสตริงเท่านั้นที่ต้องจัดรูปแบบในแบบสอบถามยังคงอยู่ในใจของนักพัฒนา แต่ในความเป็นจริงแล้ว คำขอนั้นมีองค์ประกอบประเภทต่างๆ อีกมากมาย และแต่ละอันต้องมีการจัดรูปแบบของตัวเอง!นั่นคือวิธีเดียวในการเสนอราคา () จะไม่เหมาะกับเรา แต่อย่างใด - เราต้องการเครื่องหมายคำพูดที่แตกต่างกันมากมาย และไม่ใช่ข้อยกเว้น “นี่คือ quoteName()” แต่เป็นหนึ่งในแนวคิดหลัก: แต่ละประเภทมีรูปแบบของตัวเอง เนื่องจากมีการจัดรูปแบบหลายประเภทจึงต้องระบุประเภทนั้นไว้ และตัวยึดตำแหน่งที่พิมพ์เหมาะที่สุดสำหรับสิ่งนี้

นอกจากนี้ตัวยึดตำแหน่งที่พิมพ์ยังสะดวกมาก!
ประการแรก เนื่องจากตัวดำเนินการพิเศษสำหรับการผูกค่าเข้ากับตัวยึดตำแหน่งกลายเป็นสิ่งจำเป็น (แต่ยังคงสามารถระบุประเภทของค่าที่ถูกส่งผ่านได้!)
ประการที่สอง เนื่องจากเราได้ประดิษฐ์ตัวยึดตำแหน่งที่พิมพ์ไว้ เราจึงสามารถติดตัวยึดตำแหน่งเหล่านี้จำนวนมากเพื่อแก้ไขงานประจำหลายอย่างในการเขียนคำสั่ง SQL
ก่อนอื่น เราจะสร้างตัวยึดตำแหน่งสำหรับตัวระบุ - เราพลาดสิ่งนี้ไปในชีวิตจริง ไม่ใช่จินตนาการโดยผู้เขียน API มาตรฐาน ทันทีที่นักพัฒนาต้องเผชิญกับความจำเป็นในการเพิ่มชื่อฟิลด์แบบไดนามิกให้กับคำขอ ทุกคนก็เริ่มบิดเบือนในทางของตนเอง บ้างก็เข้าไปในป่า บ้างก็เข้าไปในฟืน ที่นี่ทุกอย่างจะรวมเป็นหนึ่งเดียวกับองค์ประกอบคำขอที่เหลือ และการเพิ่มตัวระบุก็ไม่ยากไปกว่าการเพิ่มสตริง แต่ในเวลาเดียวกัน ตัวระบุนั้นไม่ได้จัดรูปแบบเป็นสตริง แต่เป็นไปตามกฎของมันเอง - มันถูกล้อมรอบด้วยเครื่องหมายคำพูดด้านหลังและภายในเครื่องหมายคำพูดเหล่านี้จะถูกหลีกหนีโดยการสองเท่า
นอกจากนี้. ปัญหาที่น่าปวดหัวต่อไปสำหรับ Developer ที่เคยลองใช้คำสั่งที่เตรียมไว้เป็นมาตรฐานในชีวิตจริงก็คือตัวดำเนินการ IN() เอาล่ะ เรามีตัวยึดตำแหน่งสำหรับการดำเนินการนี้ด้วย! การทดแทนอาร์เรย์นั้นไม่ยากไปกว่าองค์ประกอบอื่นๆ แถมด้วย แบบครบวงจรไม่มีฟังก์ชันแยกจากกันมีเพียงตัวอักษรในตัวยึดตำแหน่งเท่านั้นที่เปลี่ยนแปลง
เราสร้างตัวยึดตำแหน่งสำหรับ SET ในลักษณะเดียวกันทุกประการ ฉันไม่สามารถต้านทานการสาธิตให้เห็นว่าโค้ดกลายเป็นเรื่องง่ายเพียงใดสำหรับการสืบค้นที่สับสนเช่น INSERT... ON DUPLICATE:
$data = array("offers_in" => $in, "offers_out" => $out); $sql = "INSERT INTO stats SET pid=?i,dt=CURDATE(),?u ON DUPLICATE KEY UPDATE ?u"; $db->query($sql,$pid,$data,$data);
ปัจจุบันคลาสรองรับตัวยึดตำแหน่ง 6 ประเภท

  • ?s (“string”) - สตริง (รวมถึง DATE, FLOAT และ DECIMAL)
  • ?i (“จำนวนเต็ม”) - จำนวนเต็ม
  • ?n (“ชื่อ”) - ชื่อของเขตข้อมูลและตาราง
  • ?p (“แยกวิเคราะห์”) - เพื่อแทรกส่วนของคำขอที่ประมวลผลแล้ว
  • ?a (“อาร์เรย์”) - ชุดของค่าสำหรับ IN (สตริงเช่น "a", "b", "c")
  • ?u (“อัปเดต”) - ชุดของค่าสำหรับ SET (สตริงเช่น `field`="value", `field`="value")
ซึ่งเพียงพอสำหรับงานของฉัน แต่ชุดนี้สามารถขยายด้วยตัวยึดตำแหน่งอื่น ๆ ได้ตลอดเวลา เช่น สำหรับเศษส่วน ฉันไม่เห็นประเด็นในการสร้างตัวยึดตำแหน่งแยกต่างหากสำหรับ NULL - สามารถรวมไว้ในคำขอได้โดยตรงเสมอ
ฉันตัดสินใจที่จะไม่แปล PHP NULL เป็น SQL NULL โดยอัตโนมัติ บางทีนี่อาจทำให้โค้ดซับซ้อนเล็กน้อย (ในกรณีที่พบไม่บ่อยเมื่อจำเป็น) แต่จะลดความคลุมเครือลง

อย่างที่หลายคนอาจสังเกตเห็นแล้วว่าคลาสนี้ชวนให้นึกถึงไลบรารี DbSimple ของ Dmitry Koterov ในหลาย ๆ ด้าน แต่ฉันมีความแตกต่างพื้นฐานกับแนวคิดบางอย่างที่มีอยู่ในนั้น
ประการแรก ฉันเป็นคู่ต่อสู้ของเวทมนตร์ใดๆ เมื่อฟังก์ชันเดียวกันสามารถให้ผลลัพธ์ที่แตกต่างกันได้ ขึ้นอยู่กับประเภทของข้อมูลที่ส่งผ่าน สิ่งนี้อาจทำให้การเขียนง่ายขึ้นเล็กน้อย แต่ยังทำให้การบำรุงรักษาและการดีบักโค้ดทำได้ยากเช่นกัน ดังนั้นในชั้นเรียนของฉัน เวทมนตร์ทั้งหมดจึงถูกจำกัดให้เหลือน้อยที่สุด และการดำเนินการและประเภทข้อมูลทั้งหมดจะถูกเขียนอย่างชัดเจนเสมอ
ประการที่สอง ในความคิดของฉัน DbSimple มีไวยากรณ์ที่ซับซ้อนเกินไปเล็กน้อย ในแง่หนึ่ง เหล็กดัดฟันเป็นไอเดียที่ยอดเยี่ยม ในทางกลับกัน ทำไมเราถึงควรถ้าเรามีพลังทั้งหมดของ PHP อยู่ในมือ? ดังนั้นฉันจึงตัดสินใจไปทางอื่นและแนะนำตรรกะ "ภายนอก" ซึ่งถูกจำกัดโดยไวยากรณ์ PHP เท่านั้น แทนที่จะเป็นตรรกะ "ภายใน" - เห็นได้ชัดว่าถูกจำกัด - ตรรกะ สิ่งสำคัญคือองค์ประกอบไดนามิกใด ๆ เข้าสู่คำขอผ่านตัวยึดตำแหน่งเท่านั้น และส่วนที่เหลือขึ้นอยู่กับจินตนาการของนักพัฒนาเท่านั้น (และฟังก์ชัน parse())

รหัสชั้นเรียนมีอยู่บน Github, github.com/colshrapnel/safemysql/blob/master/safemysql.class.php
แผ่นโกงพร้อมคำสั่งพื้นฐานและตัวอย่าง: phpfaq.ru/misc/safemysql_cheatsheet_ru.pdf
สามารถรับความคิดที่ดีเกี่ยวกับความเป็นไปได้ได้จากหน้าตัวอย่างเอกสารประกอบ (น่าเสียดายที่ยังไม่เสร็จสิ้น) phpfaq.ru/safemysql
นอกจากนี้ยังมีคำตอบสำหรับคำถามที่พบบ่อย เช่น “ทำไมคุณไม่ใช้คำสั่งที่เตรียมไว้เป็นภาษาท้องถิ่น” ฯลฯ
อย่างไรก็ตาม ฉันยินดีที่จะตอบคำถามใด ๆ ในความคิดเห็น รวมถึงปรับปรุงทั้งชั้นเรียนและบทความนี้ตามความคิดเห็นของคุณ