การแสดงข้อความแก่ผู้ใช้ในเว็บแอปพลิเคชัน ไลบรารี PHP สำหรับการทำงานกับ Yandex.Money API ข้อความไม่ถูกต้อง php

ฉันอยากลองอะไรใหม่ๆ มานานแล้ว ดังนั้นเมื่ออยู่ที่ทำงาน ฉันถูกขอให้เขียนตัวอย่างการใช้ Yandex.Money API ภาษาที่แตกต่างกันฉันยินดีรับข้อเสนอการท้าทายนี้ เนื่องจากฟังก์ชันดังกล่าวมักใช้ในแอปพลิเคชันบนไซต์โฮสต์ต่างๆ จึงมีการตัดสินใจอย่างแน่วแน่ที่จะพยายามเขียนสิ่งนี้ใน PHP ก่อน ยิ่งไปกว่านั้น ฉันไม่เคยเห็น API มาก่อนด้วยซ้ำ ยิ่งไปกว่านั้น ฉันไม่มีประสบการณ์ในการทำงานกับ PHP เลย ยกเว้นงานห้องปฏิบัติการในมหาวิทยาลัย คดีนี้สัญญาว่าจะน่าสนใจ

การเลือกสภาพแวดล้อม

สิ่งแรกที่ฉันพบคือการพัฒนาและปรับใช้กับโฮสติ้งทันทีนั้นไม่สะดวกนัก และฉันตัดสินใจดาวน์โหลดชุดสุภาพบุรุษสำหรับนักพัฒนาเว็บ ตั้งแต่สมัยเป็นนักเรียน ชื่อ Denwer ปรากฏอยู่ในความทรงจำของฉัน ฉันพยายามแล้ว แต่ก็ทิ้งมันไปอย่างรวดเร็ว มันมีอายุการใช้งานของมันเอง และเมื่อฉันพยายามกำหนดค่าโดยการเขียนบางสิ่งในไฟล์ Apache conf ใหม่ มันก็เขียนทับหรือไม่ได้เขียนทับตามดุลยพินิจของตนเอง โดยไม่อนุญาตให้ฉันกำหนดค่าทุกอย่างด้วยตนเอง นั่นคือปรากฎว่าไม่ใช่ฉันที่เป็นคนตั้งค่า แต่เป็นผู้ตั้งค่าให้ฉัน ทำให้ฉันนึกถึง “ถ้าฉันมีม้า นี่คงเป็นเลข...” แน่นอนว่าในที่สุดฉันก็เอาชนะเขาได้ แต่ในขณะเดียวกันฉันก็ตัดสินใจค้นหาเซิร์ฟเวอร์ WAMP ที่เรียบง่ายกว่า ฉันอยากจะทราบว่า Denwer เป็นผลิตภัณฑ์ที่ดีและฉันไม่ได้คัดค้านอะไร แต่ฉันไม่ต้องการอ่านข้อเท็จจริงและคู่มือเกี่ยวกับผลิตภัณฑ์ดังกล่าว

ฉันพบหน้าที่มีรายการ WAMP บนวิกิ และเริ่มเรียงลำดับตามเกณฑ์หลักในการเลือกคือการสนับสนุนโปรเจ็กต์ เวอร์ชันบิลด์เป็นเวอร์ชันล่าสุดไม่มากก็น้อย และความง่ายในการติดตั้ง/รัน ด้วยเหตุนี้ฉันจึงสามารถแนะนำ The Uniform Server ได้อย่างมั่นใจ ไม่จำเป็นต้องติดตั้ง (เพียงแค่แตกไฟล์เก็บถาวร) เมื่อเริ่มต้นระบบจะค้างอยู่ในถาดและเริ่มต้นด้วยการคลิกเบา ๆ =)

การรับรองความถูกต้อง OAuth

ฉันอ่านคำแนะนำ ดาวน์โหลดเอกสาร ชักดาบแล้วรีบเข้าสู่การต่อสู้ แต่ในการต่อสู้ ฉันพ่ายแพ้อย่างรวดเร็วด้วยการรับรองความถูกต้องของ OAuth OAuth เป็นวิธีหนึ่งในการเข้าถึงบริการ/บัญชีผู้ใช้ใดๆ โดยไม่ต้องป้อนและจัดเก็บข้อมูลการเข้าสู่ระบบและรหัสผ่านในแอปพลิเคชันของคุณ สิ่งนี้มาถึงเราจากผู้สร้าง Twitter และดูเหมือนว่า: เราส่งคำขอไปยังบริการ (ในกรณีของเราคือ Yandex.Money) ผู้ใช้ป้อนชื่อผู้ใช้/รหัสผ่านของเขาบนเซิร์ฟเวอร์ Yandex.Money และให้ข้อมูลของเรา สิทธิ์การสมัครเพื่อใช้บัญชีของเขา หลังจากนี้ เซิร์ฟเวอร์ Yandex.Money เปลี่ยนเส้นทางไปยังแอปพลิเคชันของเรา และเราได้รับรหัสชั่วคราวซึ่งมีอายุการใช้งานสั้นมาก จากนั้น ด้วยการร้องขออีกครั้งไปยัง Yandex.Money เราจะเปลี่ยนรหัสชั่วคราวนี้เป็นโทเค็นผู้ใช้ถาวร จากนั้นสำหรับเรา สำหรับการถอนกำลัง ถนนทุกสายเปิดอยู่

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

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

Curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);

จำไว้นะเด็กๆ และอย่าเขียนเลย “เอาล่ะ ลูกชาย เรามาทวนคำพูดแย่ๆ เหล่านั้นที่คุณควรลืมกันเถอะ” ขอบคุณพระเจ้าที่ไม่ใช่ทุกอย่างจะแย่ขนาดนั้นบนอินเทอร์เน็ตภาษาอังกฤษ และฉันพบลิงก์ที่อธิบายทุกอย่าง ฉันทำตามที่เขียนไว้ที่นั่นและทุกอย่างทำงานได้

จากนั้นคุณต้องบันทึกใบรับรองสาธารณะของ Yandex.Money ไว้กับตัวเองเพื่อที่คุณจะได้มีสิ่งที่จะเปรียบเทียบเมื่อส่งคำขอ ดูเหมือนฉันจะไม่ปัญญาอ่อนอย่างสิ้นเชิง แต่ถึงกระนั้นฉันก็ดูเหมือนค่อนข้างยากสำหรับฉัน บางทีมันอาจช่วยคุณได้ในอนาคตเมื่อทำงานกับ SSL เราไปที่ไซต์ที่ต้องการผ่าน https คลิกที่ใบรับรองและส่งออก แต่มี 3 อันอันไหนจำเป็น? “หยิบพายจากชั้นวาง มีสองคนเอาอันกลาง” ปรากฎว่าคุณต้องส่งออกใบรับรองของผู้ออกใบรับรอง (รูท) และสื่อกลาง (Yandex) ใบรับรองขั้นสุดท้ายจะเปลี่ยนปีละครั้ง และหากเราป้อนลงในห่วงโซ่และลืมเปลี่ยนเมื่อมันเสีย ทุกอย่างในแอปพลิเคชันของเราจะเสียหาย ดังนั้นเราจึงส่งออกใบรับรอง 2 ใบที่ระบุเท่านั้นและบันทึกเป็นใบรับรองเดียว ไฟล์ข้อความ(ภาพหน้าจอ) ในห้องสมุดของฉันเขาปรากฏเป็น ym.crt.

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

การเข้ารหัส

นอกจากนี้ยังมีปัญหาเล็กน้อยในการเข้ารหัสอีกด้วย ขั้นแรก การบันทึก/กู้คืนโทเค็นผู้ใช้ถูกนำไปใช้โดยใช้ไลบรารี PHP มาตรฐาน Mcrypt แต่เมื่อปรากฎว่ามีปัญหาเกิดขึ้น ตัวอย่างเช่น จากตัวอย่างที่นำมาในคู่มือ มีเพียงฟังก์ชันที่เลิกใช้แล้วเพียงฟังก์ชันเดียวเท่านั้นที่ทำงานได้ทันที ฟังก์ชั่นที่เหลือไม่สนใจความปรารถนาของฉันที่จะทำให้มันใช้งานได้ แต่พูดเพียงบางอย่างเกี่ยวกับการเริ่มต้นโมดูลที่ไม่สำเร็จ เราต้องคิดออก ปรากฎว่าผู้โฮสต์ไม่ชอบห้องสมุดนี้มากนัก ฉันถามการสนับสนุนจากโฮสต์ของฉันว่าทำไมจึงไม่มีโมดูล Mcrypt เมื่อสร้างเว็บไซต์ใน PHP 5.3 พวกเขาตอบฉัน (ตามตัวอักษร):“ มันมีบั๊กใน 5.2 มานานหลายปีแล้ว - พวกเขาไม่ได้เพิ่มมันลงใน 5.3 โดยอัตโนมัติเป็นโมดูลที่จำได้ทุกๆ ห้าปี แต่มีปัญหากับมัน” ไลบรารีมาตรฐานอื่น ๆ ที่สะดวกสบายพร้อมการใช้งาน การเข้ารหัสแบบสมมาตรฉันไม่พบมันใน PHP (มีไลบรารี OpenSSL แต่ก็ไม่ได้มีไว้สำหรับสิ่งนี้) หลังจากนี้ ฉันตัดสินใจเปลี่ยนไลบรารีการเข้ารหัสเป็นไลบรารีหนึ่งซึ่งเปิดอยู่และรองรับอัลกอริธึม AES ยอดนิยม มันทำงานได้ทันทีและไม่มีปัญหา

ฟังก์ชั่นและตัวอย่างการใช้งาน

นอกจากนี้ สำหรับ "การฝึกแมว" หรือการทดสอบและดีบั๊ก ก็มีการเขียนการเรียกใช้ฟังก์ชันไลบรารี ซึ่งต่อมาฉันได้ปรับแต่งด้วยเลย์เอาต์ที่สบายตา เต็มไปด้วยความคิดเห็น และเรียกตัวอย่างการใช้ไลบรารี

เป็นผลให้มีการเรียกใช้ฟังก์ชัน Yandex.Money API ต่อไปนี้: ข้อมูลบัญชี ประวัติการทำธุรกรรม ข้อมูลโดยละเอียดเกี่ยวกับธุรกรรม การโอนเงินไปยังผู้ใช้รายอื่น ข้อดีและความสามารถ:

  • การอนุญาตผู้ใช้ OAuth;
  • ความปลอดภัยในการปฏิบัติงาน (รองรับการตรวจสอบห่วงโซ่ใบรับรอง)
  • ใช้งานง่าย (การตอบสนองของเซิร์ฟเวอร์จะแสดงในรูปแบบของวัตถุ) และการเริ่มต้นอย่างรวดเร็ว
  • โซลูชันที่ค่อนข้างปลอดภัยและเรียบง่ายสำหรับการจัดเก็บโทเค็นผู้ใช้โดยใช้การเข้ารหัสและไม่ใช้ฐานข้อมูล คุณสามารถเขียนการใช้งานโซลูชันนี้ใหม่สำหรับพื้นที่จัดเก็บข้อมูลของคุณได้อย่างง่ายดาย
ไลบรารีนั้นเป็นไฟล์ลูกโซ่ใบรับรอง ym.crtและไฟล์ ym.phpซึ่งประกอบด้วย:
  • อินเทอร์เฟซซอฟต์แวร์ IYandexMoney;
  • YandexMoney คลาสหลัก (การใช้งานอินเทอร์เฟซ);
  • คลาสแจงนับที่มีสิทธิ์การเข้าถึง (ขอบเขต)
  • คลาสเสริม (ออบเจ็กต์ตอบสนองสำหรับเอาต์พุตผลลัพธ์ของการร้องขอไปยัง API)
ชุดไลบรารีประกอบด้วย 2 ไฟล์ที่ใช้การเข้ารหัส: Rijndael.php และ AES.php ไฟล์เหล่านี้นำมาจากห้องสมุด จำเป็นในกรณีที่คุณใช้วิธีบันทึกและกู้คืนโทเค็น
ข้อควรระวัง: การใช้งาน เวอร์ชัน PHP 5 เช่นเดียวกับไลบรารี cUrl มาตรฐานสำหรับคำขอ http

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

YandexMoney::authorize(Consts::CLIENT_ID, "ประวัติการดำเนินการข้อมูลบัญชี", Consts::REDIRECT_URL); // จากนั้นบนหน้าเปลี่ยนเส้นทาง ให้เริ่มต้นการสร้างวัตถุและรับโทเค็น $ym = new YandexMoney(Consts::CLIENT_ID, Consts::CERTIFICATE_CHAIN_PATH); $token = $ym->receiveOAuthToken($_GET["code"], Consts::REDIRECT_URL);
เมื่อสร้างอ็อบเจ็กต์ $ym มันจะถูกส่งผ่าน ID แอปพลิเคชันและพาธสัมบูรณ์บนเซิร์ฟเวอร์ไปยังกลุ่มใบรับรอง (ไฟล์ ym.crt) โดยปกติทั้งสองโมดูลจะเขียนเป็นค่าคงที่ในบางโมดูล (consts.php ในตัวอย่างของเรา)
เราจะแสดงวิธีรับข้อมูลเกี่ยวกับบัญชีผู้ใช้ให้คุณดู ในทำนองเดียวกัน เราสร้างอ็อบเจ็กต์แล้วเรียกใช้เมธอด โดยส่งโทเค็นผู้ใช้ไปให้กับมัน:

$ym = YandexMoney ใหม่ (Consts::CLIENT_ID, Consts::CERTIFICATE_CHAIN_PATH); $accountInfoResponse = $ym->accountInfo($token); echo "หมายเลขบัญชี:" . $accountInfoResponse->getAccount() "\n"; echo "ยอดคงเหลือ:" . $accountInfoResponse->getBalance() "\n"; echo "รหัสสกุลเงิน:" . $accountInfoResponse->getCurrency() "\n";
ข้อมูลบัญชีที่ได้รับ

สถานการณ์จะเหมือนกันมากกับความท้าทายอื่นๆ

เป็นผลให้พวกเขาตัดสินใจเรียกห้องสมุดว่า SDK ชื่อใหญ่และใส่ไว้

    เอาแต่ใจตัวเอง เอาแต่ใจตัวเอง เอาแต่ใจตัวเอง ไร้ความสามารถ (ภาษาพูด). ประพฤติตามอำเภอใจ, ประพฤติตามอำเภอใจ. พจนานุกรมอธิบายของ Ushakov ดี.เอ็น. อูชาคอฟ พ.ศ. 2478 พ.ศ. 2483 ... พจนานุกรมอธิบายของ Ushakov

    จงเต็มใจ โอ้ โอ้; ไม่สมบูรณ์ (ภาษาพูด). กระทำการตามอำเภอใจ พจนานุกรมอธิบายของ Ozhegov เอสไอ Ozhegov, N.Y. ชเวโดวา พ.ศ. 2492 พ.ศ. 2535 … พจนานุกรมอธิบายของ Ozhegov

    เนซอฟ. เนเปเรห์ การสลายตัว ทำตามใจปรารถนาตามใจชอบ พจนานุกรมอธิบายของเอฟราอิม ที.เอฟ. เอฟเรโมวา 2000... พจนานุกรมอธิบายภาษารัสเซียสมัยใหม่โดย Efremova

    เอาแต่ใจตัวเอง เอาแต่ใจตัวเอง เอาแต่ใจตัวเอง เอาแต่ใจตัวเอง เอาแต่ใจตัวเอง เอาแต่ใจตัวเอง เอาแต่ใจตัวเอง เอาแต่ใจตัวเอง เอาแต่ใจตัวเอง เอาแต่ใจตัวเอง เอาแต่ใจตัวเอง เอาแต่ใจตัวเอง เอาแต่ใจตัวเอง เอาแต่ใจตัวเอง เอาแต่ใจตัวเอง เอาแต่ใจเอาแต่ใจเอาแต่ใจตัวเอง ... ... รูปแบบของคำ

    กระทำการโดยไม่ได้รับอนุญาต- หยิ่งผยอง เอ๊ย... พจนานุกรมการสะกดคำภาษารัสเซีย

    กระทำการโดยไม่ได้รับอนุญาต- (ฉัน) ฉันขี้เกียจ ฉันกำลังดื่มชา ฉันกำลังดื่มชา... พจนานุกรมตัวสะกดของภาษารัสเซีย

    ใช่แล้ว; nsv. ราซก. กระทำการตามใจปรารถนา โดยไม่ต้องขออนุญาตจากใคร ส.มาเยือน. ส.ที่ทำงาน. ทำการบ้านเอง. ◁ ความเอาแต่ใจตัวเอง ฉัน; พ อย่าเอาแต่ใจตัวเองเลย ไม่งั้นฉันจะไล่คุณออก! - พจนานุกรมสารานุกรม

    กระทำการโดยไม่ได้รับอนุญาต- โอ้โอ้; นว.; การสลายตัว ดูด้วย ความตั้งใจของตนเอง กระทำตามความปรารถนาของตนเอง ตามเจตนาของตนเอง โดยไม่ต้องขออนุญาตจากใคร Samovo / ความเกียจคร้านในงานปาร์ตี้ ซาโมโว/ขี้เกียจทำงาน ทำการบ้านด้วยตัวเอง... พจนานุกรมสำนวนมากมาย

3.3K

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

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

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

มีคนใช้การเปลี่ยนเส้นทางโดยละทิ้งข้อความที่เป็นมิตร

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

ดังนั้นเราจึงมีปัญหา - ข้อความจะต้อง "แสดง" ในคำขอที่แตกต่างกัน เราต้องการกลไกในการถ่ายโอนข้อความไปยังหน้าที่ควรจะแสดง คุณคงจำเซสชันต่างๆ ได้แล้ว

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

แนวคิดนี้ง่ายมากและสามารถนำไปใช้กับคลาสได้ 2-3 คลาส

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

class Message ( /** * Message content. */ var $content; /** * Constructor สำหรับการเริ่มต้นข้อความ * * @param content เนื้อหาข้อความ */ function Message($content) ( $this->content = $ content ; ) /** * เขียนข้อความถึง session. */ function send() ( $_SESSION["session_messages"] = $this->content; ) /** * ส่งข้อความไปยังเพจ */ function toPage () ( echo. " - " . $this->เนื้อหา
"; } }

ตัวแปร $_SESSION ใช้เพื่อเข้าถึงเซสชัน

โปรดทราบว่า $_SESSION เป็นอาร์เรย์ เราใช้เพียงองค์ประกอบเดียวของอาร์เรย์นี้กับดัชนี 'session_message'

ในกรณีนี้ เรากำลังจัดการกับ "อาร์เรย์ของอาร์เรย์" - สิ่งที่เราเก็บไว้ในองค์ประกอบ 'session_message' คืออาร์เรย์ นี่คือรายการข้อความที่ส่ง (แน่นอนว่าอาจมีได้หลายข้อความ)

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

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

โปรดทราบว่าใน ในขณะนี้ไม่ใช่วัตถุที่วางอยู่ในเซสชัน แต่เป็นเพียงข้อความเท่านั้น OOP ช่วยให้เราสามารถเปลี่ยนพฤติกรรมของเมธอด send() ได้ในภายหลัง โดยไม่ต้องเปลี่ยนโค้ดไคลเอ็นต์ที่เข้าถึงเมธอดนี้ (เช่น ในอนาคตเราสามารถเขียนออบเจ็กต์ข้อความทั้งหมดลงในเซสชันได้หากมีหลายฟิลด์)

ลองจินตนาการว่าเราจะทำเช่นนี้โดยใช้ฟังก์ชัน เราน่าจะมีฟังก์ชัน message_send($txt) และเราก็จะมีฟังก์ชัน message_to_page($txt) ด้วย ตอนนี้เราจำเป็นต้องเพิ่มความเป็นไปได้ของพฤติกรรมที่แตกต่างกันสำหรับ ประเภทต่างๆข้อความ การเรียกฟังก์ชันเปลี่ยนแปลง: message_send($txt, $kind), message_to_page($txt, $kind) คุณจะต้องค้นหาโค้ดแอปพลิเคชันทั้งหมดเพื่อค้นหาฟังก์ชันดังกล่าวและทำการแก้ไข

สิ่งนี้สามารถหลีกเลี่ยงได้โดยการคาดการณ์สถานการณ์ล่วงหน้าโดยนำเสนอข้อความเป็นอาร์เรย์ที่เชื่อมโยง: $msg['txt'], $msg['kind'] จากนั้นจะมีพารามิเตอร์เพียงตัวเดียวในการเรียกใช้ฟังก์ชัน คุณรู้สึกไหมว่าสิ่งนี้กำลังพยายามที่จะกลายเป็นชั้นเรียน?

ดังนั้น OOP เปิดโอกาสให้คุณมีความหรูหราโดยไม่ต้องคิดทุกอย่างล่วงหน้า

คลาสถัดไป - กล่องจดหมาย - มีไว้สำหรับสิ่งนี้เท่านั้น

class Inbox ( /** * Array of gets message. */ var $messages = array(); /** * ใน Constructor เราได้รับข้อความที่ได้รับทั้งหมด * และลบออกจากเซสชัน */ function Inbox() ( if (is_array($ _SESSION["session_messages"])) ( $messages = $_SESSION["session_messages"]; $co = sizeof($messages); สำหรับ ($i = 0; $i< $co; $i++) { $this->ข้อความ = ข้อความใหม่($ข้อความ[$i]);
) ) /* ล้างอาร์เรย์ข้อความ */ $_SESSION["session_messages"] = array();< $co; $i++) { $this->) /** * แสดงเนื้อหาใน Inbox บนเพจ

*/ function toPage() ( $co = sizeof($this->messages); if ($co > 0) ( echo "ข้อความจากระบบ:

"; ) สำหรับ ($i = 0; $i

ข้อความ[$i]->ToPage();

-

มาลองใช้ระบบส่งข้อความของเรากัน

มาสร้างตัวอย่างง่ายๆ ที่จะตอบสนองต่อการส่งแบบฟอร์มโดยการรายงานจำนวนวินาทีในนาทีปัจจุบัน

ส่ง(); /* เปลี่ยนเส้นทางไปยังตัวคุณเอง */ header("location:"); ) else ( $inbox = กล่องจดหมายใหม่(); $inbox->toPage(); ) ?>

เราซ่อนงานทั้งหมดที่มีอาร์เรย์และเซสชันไว้ในคลาส และโค้ดสุดท้ายก็ดูเรียบง่ายและสวยงาม
สร้างไดเร็กทอรีบนเว็บเซิร์ฟเวอร์ของคุณ จากนั้นสร้างไฟล์ทั้งสามนี้ในไดเร็กทอรีและลองใช้สคริปต์ โปรดทราบว่าไม่มีปัญหากับปุ่มย้อนกลับและรีเฟรช ตอนนี้ลองจินตนาการว่าคุณกำลังสร้างพอร์ทัลที่ซับซ้อน โดยที่ตามกฎแล้วจะมีหลายบล็อกบนเพจ และแต่ละบล็อกสามารถมีแอปพลิเคชันแยกต่างหากได้ที่นี่เราพบปัญหาสองประการ:
* ฉันต้องการให้รายการข้อความปรากฏในส่วนใดส่วนหนึ่งของหน้า และคุณพบที่ที่ดีสำหรับสิ่งนี้แล้ว ปัญหาคือคุณต้องรันคำสั่ง $inbox->toPage() ในเวลาเดียวกับตำแหน่งรายการข้อความบนเพจ หากเราต้องการเปลี่ยนตำแหน่งของรายการนี้ เราจะต้องเข้าไปในโค้ด แต่การเปลี่ยนเฟรมพอร์ทัลอย่างต่อเนื่องสำหรับสิ่งนี้ไม่ดีทางออกที่ดีที่สุด
เป็นไปได้ที่จะส่งข้อความในรูปแบบของโมดูลแยกต่างหากซึ่งทราบเพียงว่าจำเป็นต้องเชื่อมต่อกับเฟรมเท่านั้น นั่นคือปลดปล่อยตัวเองจากลำดับการเปิดตัวโมดูลที่เข้มงวด อันที่จริงเนื่องจากผลลัพธ์ของเอาต์พุต Inbox ไม่ได้ขึ้นอยู่กับการทำงานของระบบ (onขั้นตอนนี้

เมื่อต้องการแก้ไขปัญหาแรก คุณสามารถสร้างบัฟเฟอร์ที่เก็บผลลัพธ์ของผลลัพธ์ของกล่องจดหมายเข้า

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

ความพยายามในการแก้ปัญหาครั้งนี้ทำให้เรามีแนวคิดในการใช้ XML เป็นเครื่องมือในการจัดเก็บข้อมูลระดับกลาง และการใช้สไตล์ XSLT จะช่วยแก้ปัญหาที่สอง

ฉันจะไม่เน้นว่า XML คืออะไรและ XSLT คืออะไร หากคุณไม่คุ้นเคยกับสิ่งเหล่านี้ zvon.org เป็นสถานที่ที่ดีในการเริ่มค้นหา

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

ขั้นแรก ลองจินตนาการว่าส่วนหลักของโค้ดควรได้รับผลลัพธ์อย่างไร

นาทีที่ 57 ที่สอง: 45

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

class Outputable ( /** * คอนเทนเนอร์ XML (สตริง) */ var $output = ""; /** * ระบุเนื้อหาของคอนเทนเนอร์และล้างคอนเทนเนอร์ * * @return สตริงที่มีข้อมูล XML */ ฟังก์ชั่น getOutput () ( $ out = $this->output; $this->output = ""; return $out; ->output .= $string . "n" ) /** * "Abstract" method */ function toPage( ) ( ) )

เมธอด toPage() ถูกทำให้ว่างเปล่า - ในกรณีนี้จำเป็นต้องใช้เป็นตัวบ่งชี้ว่าคลาส "matryoshka" ภายนอกควรสื่อสารกับคลาสภายในอย่างไร อย่างไรก็ตาม เราสามารถเสนอการใช้งานเริ่มต้นได้ที่นี่ หากเราสังเกตเห็นว่ามีออบเจ็กต์จำนวนมากที่แสดงตัวเองบนหน้าเว็บในลักษณะเดียวกัน

คลาส Message และ Inbox จะเปลี่ยนไปเล็กน้อย - ตอนนี้ทั้งคู่ควรสืบทอดจาก Outputable และวิธีการ toPage() ก็จะเปลี่ยนไปเช่นกัน
ข้อความ.php

class Message ขยาย Outputable ( /** * Message content. */ var $content; /** * Constructor สำหรับการเริ่มต้นข้อความ * * @param content เนื้อหาข้อความ */ function Message($content) ( $this->content = $content; ) /** * เขียนข้อความไปที่ session */ function send() ( $_SESSION["session_messages"] = $this->content; ) /** * ส่งข้อความไปยังเพจ ( $ นี้->ผนวกOutput(" ".$this->เนื้อหา""); } }

class Inbox ขยาย Outputable ( /** * Array ของข้อความที่ได้รับ */ var $messages = array(); /** * ใน Constructor เราได้รับข้อความที่ได้รับทั้งหมด * และลบออกจากเซสชัน */ function Inbox( ) ( if (is_array ($_SESSION["session_messages"])) ( $messages = $_SESSION["session_messages"]; $co = sizeof($messages); สำหรับ ($i = 0; $i< $co; $i++) { $this->ข้อความ = ข้อความใหม่($ข้อความ[$i]); ) ) /* ล้างอาร์เรย์ข้อความ */ $_SESSION["session_messages"] = array();< $co; $i++) { $this->) /** * แสดงเนื้อหาใน Inbox บนเพจ"); } }

*/ function toPage() ( $co = sizeof($this->messages); $this->appendOutput("

"); สำหรับ ($i = 0; $i
ข้อความ[$i]->toPage();

$this->appendOutput($this->ข้อความ[$i]->getOutput()); ) $this->appendOutput("วิธีการส่งออกมีการเปลี่ยนแปลง - ขณะนี้ แทนที่จะส่งออกไปยังเพจโดยตรง การแสดงภายนอกจะใช้สำหรับเวลาที่ถูกจัดเก็บไว้ใน Outputable ซึ่ง "อยู่" ในแต่ละออบเจ็กต์ วิธีการ appendOutput() ทำหน้าที่แทนโครงสร้าง echo() ในการรับเอาต์พุตของอ็อบเจ็กต์ จะใช้เมธอด getOutput() ทีนี้มาดูกันว่าส่วนไคลเอนต์ของโค้ดคืออะไรซึ่งจะแก้ปัญหาเดิมได้ดัชนี.php


ส่ง();   /* วินาทีปัจจุบัน */ $msg_sec = ข้อความใหม่("วินาที: " . date("s"));
"; ?>

$msg_sec->ส่ง(); /* เปลี่ยนเส้นทางไปยังตัวคุณเอง */ header("location:");ออก; ) else ( /* เตรียมรายการข้อความในรูปแบบ XML */ $inbox = new Inbox(); $inbox->toPage(); $global_content->appendOutput($inbox->getOutput()); ) $global_content- >ผนวกเอาต์พุต ("

"); $xml_string = $global_content->getOutput(); $xh = xslt_create(); $xarg = array(); /* ส่วนหัวของเอกสาร XML */ $xarg["xml"] = "

หากต้องการดูผลลัพธ์ สิ่งที่เหลืออยู่คือการเตรียมเทมเพลต XSL
สไตล์.xsl

ตัวอย่าง XSLT

ข้อความ

เราประสบความสำเร็จอะไรบ้าง?

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

โมดูลใดๆ ที่สร้างข้อมูล XML จากการทำงานสามารถนำมาใช้ในโครงการได้ อย่างไรก็ตาม นี่เป็นข้อดีประการหนึ่งเหนือเอ็นจิ้นเทมเพลตซึ่งการสร้างข้อมูลประกอบด้วยลำดับวิธีการเรียก (กำหนด ฯลฯ ) ของเอ็นจิ้นเฉพาะซึ่งไม่มีมาตรฐานทั่วไป

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

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

ในที่สุด การควบม้าเกี่ยวกับโอกาส:

* หน้าต่างป๊อปอัปสำหรับรายการข้อความสำคัญ
* "หน้าผู้ส่ง" และ "หน้าปลายทาง" ในข้อความ
* บันทึกข้อความในฐานข้อมูล
* ปุ่ม "แสดงประวัติการกระทำของฉัน"
* การวิเคราะห์ทางสถิติของการกระทำของผู้ใช้ภายในเซสชัน
* "ผู้ช่วยอัจฉริยะ" ในเว็บแอปพลิเคชัน

สวัสดีทุกคน!

ในฉบับที่แล้ว เราได้เรียนรู้วิธีการประมวลผลสัญญาณที่ได้รับเดียวกันนี้อย่างถูกต้องแล้ว ตอนนี้เราเข้าใกล้ช่วงเวลาที่ปีศาจของเราต้องเรียนรู้ที่จะสื่อสารกับโปรแกรมอื่นหรือกับตัวมันเอง แต่ในรูปแบบที่แตกต่างกัน

ในโลกของระบบปฏิบัติการยูนิกซ์ มีหลายวิธีในการส่งคำสั่งหรือข้อความจากดีมอนไปยังเว็บสคริปต์และในทางกลับกัน แต่ตอนนี้ฉันต้องการพูดเฉพาะเกี่ยวกับคิวข้อความ - "คิวข้อความ System V IPC"

เมื่อเป็นเด็ก คุณแม่ของคุณคงบอกคุณไปแล้วว่าคิวสามารถพบได้ทั้งในการติดตั้ง System V IPC และการใช้งาน Posix ฉันต้องการสัมผัสเฉพาะหัวข้อของ System V เท่านั้นเนื่องจากเป็นเรื่องใกล้ตัวฉันเป็นการส่วนตัว และฉันจะพยายามหลีกเลี่ยงหัวข้อ posix ถ้าเป็นไปได้

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

นี่เป็นการสรุปส่วนเบื้องต้น เรามาฝึกกันต่อ

การส่งข้อความ

คิว send.php

เรายอมรับข้อความ

คิวรับ.php

มารันไฟล์ทีละไฟล์กันก่อน คิว send.phpแล้ว คิวรับ.php.

U% php Queue-send.php ส่ง 4 ข้อความ u% php Queue-receive.php ประเภท: 1 ประเภท: 1, msgtype: 1, ข้อความ: s:15: "ข้อความ, ประเภท 1"; ประเภท: 1, msgtype: 1, ข้อความ: s:15:"ข้อความ พิมพ์ 1"; ประเภท: 2 ประเภท: 2, msgtype: 2, ข้อความ: s:15:"ข้อความ, ประเภท 2"; ประเภท: 3 ประเภท: 3, msgtype: 3, ข้อความ: s:15:"ข้อความ, ประเภท 3";

คุณจะเห็นว่าข้อความถูกจัดกลุ่มไว้ และข้อความประเภทแรก 2 ข้อความจะแสดงก่อน จากนั้นจึงแสดงข้อความอื่นๆ ทั้งหมด
หากเรากำหนดให้รับข้อความประเภท 0 เราก็จะได้รับข้อความทั้งหมดโดยไม่คำนึงถึงประเภท

ในขณะที่ (msg_receive($queue, $i, $msgtype, 4096, $message, false, MSG_IPC_NOWAIT)) ( // ...

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

คิวรับรอ.php

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

ตอนนี้เรามาลองเขียน daemon ที่ฟังคิว:
คิว daemon.php