ไมโครเฟรมเวิร์ก PHP ที่ทรงพลังแต่ใช้งานง่าย ออกแบบมาเพื่อช่วยคุณสร้างเว็บแอปพลิเคชันแบบไดนามิกและแข็งแกร่ง - รวดเร็ว!
ด้วยการบีบอัดไฟล์ขนาด ~65KB เพียงไฟล์เดียว F3 (ตามที่เราเรียกกันว่าสิ่งนี้) จะให้รากฐานที่มั่นคง ฐานโค้ดที่สมบูรณ์ และแนวทางที่ไร้สาระในการเขียนเว็บแอปพลิเคชัน เบื้องหลังคือชุดเครื่องมือพัฒนาเว็บที่ใช้งานง่าย กลไกการกำหนดเส้นทาง URL และแคชประสิทธิภาพสูง การเน้นโค้ดในตัว และรองรับแอปพลิเคชันหลายภาษา มันมีน้ำหนักเบา ใช้งานง่าย และรวดเร็ว ส่วนใหญ่มันไม่ได้ขวางทางคุณ
ไม่ว่าคุณจะเป็นมือใหม่หรือเป็นโปรแกรมเมอร์ PHP ที่เชี่ยวชาญ F3 จะช่วยให้คุณพร้อมใช้งานได้ทันที ไม่มีขั้นตอนการติดตั้งที่ไม่จำเป็นและอุตสาหะ ไม่จำเป็นต้องมีการกำหนดค่าที่ซับซ้อน ไม่มีโครงสร้างไดเรกทอรีที่ซับซ้อน ไม่มีเวลาใดที่จะดีไปกว่าการเริ่มพัฒนาเว็บแอปพลิเคชั่นด้วยวิธีที่ง่ายไปกว่าตอนนี้!
F3 รองรับทั้งฐานข้อมูล SQL และ NoSQL ที่มีอยู่ทั่วไป: MySQL, SQLite, MSSQL/Sybase, PostgreSQL, DB2 และ MongoDB นอกจากนี้ยังมาพร้อมกับตัวแมปเชิงวัตถุสัมพันธ์อันทรงพลังสำหรับการแยกข้อมูลและการสร้างแบบจำลองข้อมูลซึ่งมีน้ำหนักเบาพอ ๆ กับเฟรมเวิร์ก ไม่จำเป็นต้องกำหนดค่า
นั่นไม่ใช่ทั้งหมด F3 มาพร้อมกับปลั๊กอินเสริมอื่นๆ ที่ขยายขีดความสามารถ:-
ไม่เหมือนกับเฟรมเวิร์กอื่นๆ F3 ตั้งเป้าที่จะใช้งานได้ - ไม่ปกติ
ปรัชญาเบื้องหลังเฟรมเวิร์กและแนวทางสถาปัตยกรรมซอฟต์แวร์มุ่งสู่ความเรียบง่ายในส่วนประกอบโครงสร้าง หลีกเลี่ยงความซับซ้อนของแอปพลิเคชัน และสร้างสมดุลระหว่างความสง่างามของโค้ด ประสิทธิภาพของแอปพลิเคชัน และประสิทธิภาพของโปรแกรมเมอร์
F3 มีสถาปัตยกรรมระดับองค์กรที่มีความเสถียร ประสิทธิภาพที่เหนือชั้น คุณสมบัติที่เป็นมิตรต่อผู้ใช้ และขนาดที่เบา คุณสามารถขออะไรเพิ่มเติมได้บ้าง? หากต้องการรับแพ็คเกจนี้ เพียงดาวน์โหลดแพ็คเกจนี้หรือไปที่พื้นที่เก็บข้อมูล fatfree-core เพื่อค้นหา Edge-version ล่าสุด
สำหรับผู้ใช้นักแต่งเพลงทุกคน:
composer create-project bcosca/fatfree
composer require bcosca/fatfree-core
ขอแนะนำอย่างยิ่งให้ผู้ใช้ที่มีประสบการณ์พัฒนาแอปพลิเคชันใหม่ด้วยเวอร์ชันล่าสุดเพื่อใช้ประโยชน์จากฐานโค้ดที่อัปเดตและการปรับปรุงอย่างต่อเนื่อง
คู่มือผู้ใช้ล่าสุดและเอกสารประกอบ API โดยละเอียดพร้อมตัวอย่างโค้ดจำนวนมากและคำแนะนำแบบกราฟิกสามารถดูได้ที่ fatfreeframework.com/
แน่นอนว่าข้อมูลอ้างอิงออนไลน์ที่มีประโยชน์นี้ขับเคลื่อนโดย F3! มันแสดงให้เห็นถึงความสามารถและประสิทธิภาพของกรอบงาน ตรวจสอบออกตอนนี้ หากคุณต้องการอ่านโดยตรงที่ GitHub คุณสามารถค้นหาเนื้อหาเว็บไซต์ได้ที่ github.com/F3Community/F3com-data
นักออกแบบรู้ว่าเขาบรรลุความสมบูรณ์แบบไม่ใช่เมื่อไม่มีอะไรเหลือให้เพิ่ม แต่เมื่อไม่มีอะไรเหลือที่จะนำออกไป -- อองตวน เดอ แซงเต็กซูเปรี
Fat-Free Framework ทำให้การสร้างเว็บไซต์ทั้งหมดเป็นเรื่องง่ายในระยะเวลาอันสั้น ด้วยพลังและความกะทัดรัดเช่นเดียวกับชุดเครื่องมือและไลบรารี Javascript สมัยใหม่ F3 ช่วยให้คุณเขียนโปรแกรม PHP ที่ดูดีขึ้นและเชื่อถือได้มากขึ้น ดูซอร์สโค้ด PHP ของคุณเพียงครั้งเดียว แล้วทุกคนจะพบว่ามันเข้าใจง่าย คุณสามารถบรรลุผลสำเร็จได้มากเพียงใดในโค้ดเพียงไม่กี่บรรทัด และผลลัพธ์ที่ได้นั้นทรงพลังเพียงใด
F3 เป็นหนึ่งในเฟรมเวิร์กที่มีการจัดทำเอกสารที่ดีที่สุด การเรียนรู้มันไม่มีค่าใช้จ่ายเลย ไม่มีชุดโครงสร้างไดเร็กทอรีที่ยากต่อการนำทางที่เข้มงวดและขั้นตอนการเขียนโปรแกรมที่น่ารำคาญ ไม่มีตัวเลือกการกำหนดค่าสำหรับรถบรรทุกเพียงเพื่อแสดง 'Hello, World'
ในเบราว์เซอร์ของคุณ Fat-Free ให้อิสระและสไตล์แก่คุณมากมาย เพื่อให้งานเสร็จได้มากขึ้นอย่างง่ายดายและใช้เวลาน้อยลง
แนวทางการเขียนโปรแกรมของ F3 ช่วยให้มือใหม่และผู้เชี่ยวชาญเข้าใจโค้ด PHP ได้อย่างง่ายดาย หากคุณคุ้นเคยกับภาษาการเขียนโปรแกรม Ruby คุณจะสังเกตเห็นความคล้ายคลึงระหว่างไมโครเฟรมเวิร์กแบบ Fat-Free และ Sinatra เนื่องจากทั้งสองภาษาใช้ภาษาเฉพาะโดเมนอย่างง่ายสำหรับบริการเว็บ ReSTful แต่แตกต่างจาก Sinatra และรูปแบบ PHP ของมัน (Fitzgerald, Limonade, Glue และอื่นๆ อีกมากมาย) Fat-Free เป็นมากกว่าแค่การจัดการเส้นทางและคำขอเท่านั้น มุมมองสามารถอยู่ในรูปแบบใดก็ได้ เช่น ข้อความธรรมดา, HTML, XML หรือข้อความอีเมล เฟรมเวิร์กมาพร้อมกับเอ็นจิ้นเทมเพลตที่รวดเร็วและใช้งานง่าย F3 ยังทำงานได้อย่างราบรื่นกับกลไกเทมเพลตอื่นๆ รวมถึง Twig, Smarty และ PHP เอง โมเดลสื่อสารกับผู้แมปข้อมูลของ F3 และผู้ช่วยเหลือ SQL เพื่อการโต้ตอบที่ซับซ้อนยิ่งขึ้นกับกลไกฐานข้อมูลต่างๆ ปลั๊กอินอื่นๆ ขยายฟังก์ชันพื้นฐานให้มากยิ่งขึ้น เป็นกรอบการพัฒนาเว็บโดยรวม - เต็มไปด้วยกล้ามเนื้อมากมาย!
คลายซิปเนื้อหาของแพ็คเกจการแจกจ่ายที่ใดก็ได้ในฮาร์ดไดรฟ์ของคุณ ตามค่าเริ่มต้น ไฟล์เฟรมเวิร์กและปลั๊กอินเสริมจะอยู่ใน lib/
path จัดระเบียบโครงสร้างไดเร็กทอรีของคุณในแบบที่คุณต้องการ คุณสามารถย้ายโฟลเดอร์เริ่มต้นไปยังเส้นทางที่ไม่สามารถเข้าถึงเว็บได้เพื่อความปลอดภัยที่ดีขึ้น ลบปลั๊กอินที่คุณไม่ต้องการ คุณสามารถกู้คืนได้ในภายหลังและ F3 จะตรวจจับการมีอยู่โดยอัตโนมัติ
สิ่งสำคัญ: หากแอปพลิเคชันของคุณใช้ APC, Memcached, WinCache, XCache หรือแคชของระบบไฟล์ ให้ล้างรายการแคชทั้งหมดก่อนที่จะเขียนทับเฟรมเวิร์กเวอร์ชันเก่าด้วยอันใหม่
ตรวจสอบให้แน่ใจว่าคุณใช้ PHP เวอร์ชันที่ถูกต้อง F3 ไม่รองรับเวอร์ชันที่เก่ากว่า PHP 7.2 คุณจะได้รับข้อผิดพลาดทางไวยากรณ์ (ผลบวกลวง) ทั่วทุกแห่งเนื่องจาก PHP เวอร์ชันเก่าไม่รองรับโครงสร้างภาษาใหม่และการปิด/ฟังก์ชันที่ไม่ระบุชื่อ หากต้องการทราบ ให้เปิดคอนโซลของคุณ ( bash
shell บน GNU/Linux หรือ cmd.exe
บน Windows):-
/path/to/php -v
PHP จะแจ้งให้คุณทราบว่าคุณกำลังใช้งานเวอร์ชันใดอยู่ และคุณควรจะได้สิ่งที่มีลักษณะคล้ายกับสิ่งนี้:-
PHP 7.4.21 (cli) (built: Jul 27 2021 15:56:07) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
with Xdebug v2.9.8, Copyright (c) 2002-2020, by Derick Rethans
อัปเกรดหากจำเป็น และกลับมาที่นี่หากคุณได้ข้ามไปเป็น PHP 7.4 หรือรุ่นที่ใหม่กว่า Fatfree ต้องการ PHP 7.2 เป็นอย่างน้อยจึงจะทำงานได้ หากคุณต้องการผู้ให้บริการโฮสติ้ง ให้ลองใช้บริการเหล่านี้:
ถึงเวลาเริ่มเขียนใบสมัครครั้งแรกของเรา:-
$ f3 = require ( ' path/to/base.php ' );
$ f3 -> route ( ' GET / ' ,
function () {
echo ' Hello, world! ' ;
}
);
$ f3 -> run ();
นำหน้า base.php
ในบรรทัดแรกด้วยพาธที่เหมาะสม บันทึกส่วนของโค้ดด้านบนเป็น index.php
ในโฟลเดอร์รูทเว็บของคุณ เราได้เขียนหน้าเว็บแรกของเรา
ใช้ผู้แต่งเหรอ? จากนั้นเพียงเรียกใช้ composer require bcosca/fatfree
และใช้สิ่งต่อไปนี้:
require ' vendor/autoload.php ' ;
$ f3 = Base:: instance ();
$ f3 -> route ( ' GET / ' ,
function () {
echo ' Hello, world! ' ;
}
);
$ f3 -> run ();
คำสั่งแรกจะบอกล่าม PHP ว่าคุณต้องการให้ฟังก์ชันและคุณสมบัติของเฟรมเวิร์กพร้อมใช้งานสำหรับแอปพลิเคชันของคุณ เมธอด $f3->route()
แจ้ง Fat-Free ว่าเว็บเพจพร้อมใช้งานที่ URL ที่เกี่ยวข้องซึ่งระบุด้วยเครื่องหมายทับ ( /
) ใครก็ตามที่เข้าชมไซต์ของคุณที่ http://www.example.com/
จะเห็นข้อความ 'Hello, world!'
ข้อความเนื่องจาก URL /
เทียบเท่ากับรูทเพจ หากต้องการสร้างเส้นทางที่แยกออกจากรูทเพจ เช่น http://www.example.com/inside/
คุณสามารถกำหนดเส้นทางอื่นด้วยสตริง GET /inside
แบบธรรมดา
เส้นทางที่อธิบายไว้ข้างต้นจะบอกเฟรมเวิร์กให้เรนเดอร์เพจเฉพาะเมื่อได้รับการร้องขอ URL โดยใช้เมธอด HTTP GET
เว็บไซต์ที่ซับซ้อนมากขึ้นซึ่งมีแบบฟอร์มใช้วิธีการ HTTP อื่น ๆ เช่น POST
และคุณยังสามารถใช้รูปแบบนั้นเป็นส่วนหนึ่งของข้อกำหนด $f3->route()
หากเฟรมเวิร์กเห็นคำขอขาเข้าสำหรับเว็บเพจของคุณซึ่งอยู่ที่ URL รูท /
กรอบงานจะกำหนดเส้นทางคำขอไปยังฟังก์ชันโทรกลับโดยอัตโนมัติ ซึ่งมีโค้ดที่จำเป็นในการประมวลผลคำขอและแสดงผลเนื้อหา HTML ที่เหมาะสม ในตัวอย่างนี้ เราเพียงแค่ส่งสตริง 'Hello, world!'
ไปยังเว็บเบราว์เซอร์ของผู้ใช้
ดังนั้นเราจึงได้กำหนดเส้นทางแรกของเรา แต่นั่นจะไม่ช่วยอะไรมากนัก ยกเว้นเพื่อให้ F3 รู้ว่ามีกระบวนการที่จะจัดการมันและมีข้อความบางส่วนที่จะแสดงบนเว็บเบราว์เซอร์ของผู้ใช้ หากคุณมีหน้าเว็บจำนวนมากในไซต์ของคุณ คุณจะต้องกำหนดเส้นทางที่แตกต่างกันสำหรับแต่ละกลุ่ม สำหรับตอนนี้ เรามาทำให้มันง่ายกันดีกว่า เพื่อสั่งให้เฟรมเวิร์กเริ่มรอคำขอ เราใช้คำสั่ง $f3->run()
ไม่สามารถเรียกใช้ตัวอย่างได้ใช่ไหม หากคุณประสบปัญหาในการทำให้โปรแกรมง่ายๆ นี้ทำงานบนเซิร์ฟเวอร์ของคุณ คุณอาจต้องปรับแต่งการตั้งค่าเว็บเซิร์ฟเวอร์เล็กน้อย ดูตัวอย่างการกำหนดค่า Apache ในส่วนต่อไปนี้ (พร้อมกับ Nginx และ Lighttpd ที่เทียบเท่ากัน)
ยังคงประสบปัญหาใช่ไหม? ตรวจสอบให้แน่ใจว่า $f3 = require('path/to/base.php');
การมอบหมายงานมาก่อนเอาต์พุตใดๆ ในสคริปต์ของคุณ base.php
แก้ไขส่วนหัว HTTP ดังนั้นอักขระใดๆ ที่ส่งออกไปยังเบราว์เซอร์ก่อนการกำหนดนี้จะทำให้เกิดข้อผิดพลาด
ตัวอย่างแรกของเราไม่ยากเกินไปที่จะกลืนใช่ไหม? หากคุณชอบรสชาติซุปปลอดไขมันเพิ่มขึ้นอีกเล็กน้อย ให้ใส่เส้นทางอื่นก่อนคำสั่ง $f3->run()
:-
$ f3 -> route ( ' GET /about ' ,
function () {
echo ' Donations go to a local charity... us! ' ;
}
);
คุณไม่ต้องการที่จะเกะกะเนมสเปซส่วนกลางด้วยชื่อฟังก์ชันใช่ไหม Fat-Free รับรู้ถึงวิธีการต่างๆ ในการแมปตัวจัดการเส้นทางกับคลาสและวิธีการของ OOP:-
class WebPage {
function display () {
echo ' I cannot object to an object ' ;
}
}
$ f3 -> route ( ' GET /about ' , ' WebPage->display ' );
คำขอ HTTP สามารถกำหนดเส้นทางไปยังวิธีการเรียนแบบคงที่: -
$ f3 -> route ( ' GET /login ' , ' Auth::login ' );
อาร์กิวเมนต์ที่ส่งผ่านจะถูกระบุเป็นพารามิเตอร์ตัวที่สองเสมอ:
$ f3 -> route ( ' GET /hello/@name ' , ' User::greet ' );
class User {
public static function greet ( $ f3 , $ args ) { // $ args is type of Array
echo " Hello " . $ args [ ' name ' ];
}
}
หากอาร์กิวเมนต์ชื่อที่ระบุเป็น foo (/hello/foo) ผลลัพธ์ต่อไปนี้จะปรากฏขึ้น:
Hello foo
ในการสาธิตภาษาเฉพาะโดเมน (DSL) อันทรงพลังของ Fat-Free คุณสามารถระบุเส้นทางเดียวเพื่อจัดการกับความเป็นไปได้ที่แตกต่างกัน:-
$ f3 -> route ( ' GET /brew/@count ' ,
function ( $ f3 ) {
echo $ f3 -> get ( ' PARAMS.count ' ). ' bottles of beer on the wall. ' ;
}
);
ตัวอย่างนี้แสดงวิธีที่เราสามารถระบุโทเค็น @count
เพื่อแสดงส่วนหนึ่งของ URL กรอบงานจะให้บริการ URL คำขอใด ๆ ที่ตรงกับคำนำหน้า /brew/
เช่น /brew/99
, /brew/98
ฯลฯ ซึ่งจะแสดง '99 bottles of beer on the wall'
และ '98 bottles of beer on the wall'
ตามลำดับ Fat-Free จะยอมรับคำขอเพจ /brew/unbreakable
ด้วย (คาดว่าสิ่งนี้จะแสดง 'unbreakable bottles of beer on the wall'
) เมื่อมีการระบุเส้นทางแบบไดนามิกดังกล่าว Fat-Free จะสร้างตัวแปรอาร์เรย์ PARAMS
ส่วนกลางโดยอัตโนมัติด้วยค่าของสตริงที่บันทึกไว้ใน URL การเรียก $f3->get()
ภายในฟังก์ชัน callback จะดึงค่าของตัวแปรเฟรมเวิร์ก คุณสามารถใช้วิธีนี้กับโค้ดของคุณเป็นส่วนหนึ่งของการนำเสนอหรือตรรกะทางธุรกิจได้อย่างแน่นอน แต่เราจะหารือเรื่องนี้โดยละเอียดยิ่งขึ้นในภายหลัง
โปรดสังเกตว่า Fat-Free เข้าใจสัญลักษณ์จุดอาร์เรย์ คุณสามารถใช้สัญลักษณ์ปกติ PARAMS['count']
แทนในโค้ดได้ ซึ่งมีแนวโน้มที่จะพิมพ์ผิดและวงเล็บปีกกาไม่สมดุล ในมุมมองและเทมเพลต กรอบงานอนุญาตให้ใช้สัญลักษณ์ @PARAMS.count
ซึ่งค่อนข้างคล้ายกับ Javascript (เราจะกล่าวถึงมุมมองและเทมเพลตในภายหลัง)
นี่เป็นอีกวิธีหนึ่งในการเข้าถึงโทเค็นในรูปแบบคำขอ:-
$ f3 -> route ( ' GET /brew/@count ' ,
function ( $ f3 , $ params ) {
echo $ params [ ' count ' ]. ' bottles of beer on the wall. ' ;
}
);
คุณสามารถใช้เครื่องหมายดอกจัน ( *
) เพื่อยอมรับ URL ใดๆ หลังเส้นทาง /brew
- หากคุณไม่สนใจเส้นทางที่เหลือ:-
$ f3 -> route ( ' GET /brew/* ' ,
function () {
echo ' Enough beer! We always end up here. ' ;
}
);
จุดสำคัญที่ควรพิจารณา: คุณจะสับสนว่า Fat-Free (และตัวคุณเอง) สับสนหากคุณมีทั้ง GET /brew/@count
และ GET /brew/*
รวมกันในแอปพลิเคชันเดียวกัน ใช้อย่างใดอย่างหนึ่ง อีกประการหนึ่ง: Fat-Free มองว่า GET /brew
แยกและแตกต่างจากเส้นทาง GET /brew/@count
แต่ละคนสามารถมีตัวจัดการเส้นทางที่แตกต่างกันได้
รอสักครู่ - ในตัวอย่างก่อนหน้านี้ทั้งหมด เราไม่เคยสร้างไดเร็กทอรีใดๆ ในฮาร์ดไดรฟ์ของเราเพื่อจัดเก็บเส้นทางเหล่านี้เลย คำตอบสั้นๆ: เราไม่จำเป็นต้องทำ เส้นทาง F3 ทั้งหมดเป็นเสมือน พวกเขาไม่ได้จำลองโครงสร้างโฟลเดอร์ฮาร์ดดิสก์ของเรา หากคุณมีโปรแกรมหรือไฟล์คงที่ (รูปภาพ, CSS ฯลฯ) ที่ไม่ได้ใช้เฟรมเวิร์ก - ตราบใดที่เส้นทางไปยังไฟล์เหล่านี้ไม่ขัดแย้งกับเส้นทางใด ๆ ที่กำหนดไว้ในแอปพลิเคชันของคุณ - ซอฟต์แวร์เซิร์ฟเวอร์เว็บของคุณจะส่งพวกเขาไปยัง เบราว์เซอร์ของผู้ใช้ โดยที่เซิร์ฟเวอร์ได้รับการกำหนดค่าอย่างถูกต้อง
เมื่อคุณกำหนดเส้นทาง คุณสามารถตั้งชื่อได้ ใช้ชื่อเส้นทางในโค้ดและเทมเพลตของคุณแทน URL ที่พิมพ์ จากนั้น หากคุณต้องการเปลี่ยน URL ของคุณเพื่อทำให้ผู้บริหารฝ่ายการตลาดพอใจ คุณเพียงแค่ทำการเปลี่ยนแปลงตำแหน่งที่กำหนดเส้นทางเท่านั้น ชื่อเส้นทางต้องเป็นไปตามกฎการตั้งชื่อตัวแปร PHP (ไม่มีจุด ขีดกลาง หรือขีดกลาง)
ลองตั้งชื่อเส้นทาง:-
$ f3 -> route ( ' GET @beer_list: /beer ' , ' Beer->list ' );
ชื่อจะถูกแทรกหลังเส้นทาง VERB ( GET
ในตัวอย่างนี้) นำหน้าด้วยสัญลักษณ์ @
และแยกออกจากส่วน URL ด้วยเครื่องหมายโคลอน :
คุณสามารถแทรกช่องว่างหลังเครื่องหมายโคลอนได้ ซึ่งจะทำให้อ่านโค้ดของคุณได้ง่ายขึ้น (ดังที่แสดงไว้ที่นี่)
หากต้องการเข้าถึงเส้นทางที่มีชื่อในเทมเพลต ให้รับค่าของเส้นทางที่มีชื่อเป็นคีย์ของอาร์เรย์ไฮฟ์ ALIASES
:-
< a href =" {{ @ALIASES.beer_list }} " > View beer list </ a >
หากต้องการเปลี่ยนเส้นทางผู้เยี่ยมชมไปยัง URL ใหม่ ให้เรียกเส้นทางที่มีชื่อภายในวิธี reroute()
เช่น: -
// a named route is a string value
$ f3 -> reroute ( ' @beer_list ' ); // note the single quotes
หากคุณใช้โทเค็นในเส้นทางของคุณ F3 จะแทนที่โทเค็นเหล่านั้นด้วยค่าปัจจุบัน หากคุณต้องการเปลี่ยนค่าของโทเค็นก่อนที่จะเรียกเส้นทางใหม่ ให้ส่งผ่านเป็นอาร์กิวเมนต์ที่ 2:-
$ f3 -> route ( ' GET @beer_list: /beer/@country ' , ' Beer->bycountry ' );
$ f3 -> route ( ' GET @beer_list: /beer/@country/@village ' , ' Beer->byvillage ' );
// a set of key - value pairs is passed as argument to named route
$ f3 -> reroute ( ' @beer_list(@country=Germany) ' );
// if more than one token needed
$ f3 -> reroute ( ' @beer_list(@country=Germany,@village=Rhine) ' );
อย่าลืม urlencode()
อาร์กิวเมนต์ของคุณหากคุณมีอักขระที่ไม่เป็นไปตามหลักเกณฑ์ RFC 1738 สำหรับ URL ที่มีรูปแบบถูกต้อง
เวอร์ชันเสถียรล่าสุดของ PHP มีเว็บเซิร์ฟเวอร์ในตัว เริ่มต้นใช้งานโดยใช้การกำหนดค่าต่อไปนี้: -
php -S localhost:80 -t /var/www/
คำสั่งดังกล่าวจะเริ่มกำหนดเส้นทางคำขอทั้งหมดไปยังรูทเว็บ /var/www
หากได้รับคำขอ HTTP ขาเข้าสำหรับไฟล์หรือโฟลเดอร์ PHP จะค้นหาคำขอนั้นภายในรูทของเว็บ และส่งไปยังเบราว์เซอร์หากพบ มิฉะนั้น PHP จะโหลดค่า index.php
(ซึ่งมีโค้ดที่เปิดใช้งาน F3 ของคุณ)
หากคุณใช้ Apache ตรวจสอบให้แน่ใจว่าคุณเปิดใช้งานโมดูลการเขียน URL ใหม่ (mod_rewrite) ในไฟล์ apache.conf (หรือ httpd.conf) คุณควรสร้างไฟล์ .htaccess ที่มีสิ่งต่อไปนี้:-
# Enable rewrite engine and route requests to framework
RewriteEngine On
# Some servers require you to specify the `RewriteBase` directive
# In such cases, it should be the path (relative to the document root)
# containing this .htaccess file
#
# RewriteBase /
RewriteRule ^(tmp)/|.ini$ - [R=404]
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php [L,QSA]
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
สคริปต์บอก Apache ว่าเมื่อใดก็ตามที่คำขอ HTTP มาถึงและหากไม่มีไฟล์ฟิสิคัล ( !-f
) หรือพาธ ( !-d
) หรือลิงก์สัญลักษณ์ ( !-l
) ควรถ่ายโอนการควบคุมไปยัง index.php
ซึ่งมี ตัวควบคุมหลัก/ด้านหน้าของเรา และในทางกลับกัน จะเรียกใช้เฟรมเวิร์ก
.htaccess file
ที่มีคำสั่ง Apache ที่ระบุไว้ข้างต้นควรอยู่ในโฟลเดอร์เดียวกันกับ index.php
เสมอ
คุณต้องตั้งค่า Apache เพื่อให้ทราบตำแหน่งทางกายภาพของ index.php
ในฮาร์ดไดรฟ์ของคุณ การกำหนดค่าทั่วไปคือ:-
DocumentRoot " /var/www/html "
< Directory "/var/www/html">
Options -Indexes +FollowSymLinks +Includes
AllowOverride All
Order allow,deny
Allow from All
</ Directory >
หากคุณกำลังพัฒนาหลายแอปพลิเคชันพร้อมกัน การกำหนดค่าโฮสต์เสมือนจะจัดการได้ง่ายกว่า:-
NameVirtualHost *
< VirtualHost *>
ServerName site1.com
DocumentRoot " /var/www/site1 "
< Directory "/var/www/site1">
Options -Indexes +FollowSymLinks +Includes
AllowOverride All
Order allow,deny
Allow from All
</ Directory >
</ VirtualHost >
< VirtualHost *>
ServerName site2.com
DocumentRoot " /var/www/site2 "
< Directory "/var/www/site2">
Options -Indexes +FollowSymLinks +Includes
AllowOverride All
Order allow,deny
Allow from All
</ Directory >
</ VirtualHost >
แต่ละ ServerName
( site1.com
และ site2.com
ในตัวอย่างของเรา) จะต้องแสดงรายการอยู่ในไฟล์ /etc/hosts
ของคุณ บน Windows คุณควรแก้ไข C:/WINDOWS/system32/drivers/etc/hosts
อาจจำเป็นต้องรีบูตเพื่อให้การเปลี่ยนแปลงมีผล จากนั้นคุณสามารถชี้เว็บเบราว์เซอร์ของคุณไปยังที่อยู่ http://site1.com
หรือ http://site2.com
โฮสต์เสมือนทำให้แอปพลิเคชันของคุณปรับใช้ได้ง่ายขึ้นมาก
สำหรับเซิร์ฟเวอร์ Nginx นี่คือการกำหนดค่าที่แนะนำ (แทนที่ ip_address:port ด้วยการตั้งค่า FastCGI PHP ของสภาพแวดล้อมของคุณ):-
server {
root /var/www/html;
location / {
index index.php index.html index.htm;
try_files $uri $uri / /index.php? $query_string ;
}
location ~ .php$ {
fastcgi_pass ip_address:port;
include fastcgi_params;
}
}
เซิร์ฟเวอร์ Lighttpd ได้รับการกำหนดค่าในลักษณะที่คล้ายกัน: -
$HTTP["host"] =~ "www.example.com$" {
url.rewrite-once = ( "^/(.*?)(?.+)?$"=>"/index.php/$1?$2" )
server.error-handler-404 = "/index.php"
}
ติดตั้งโมดูลการเขียน URL ใหม่และเฟรมเวิร์ก .NET ที่เหมาะสมซึ่งสอดคล้องกับเวอร์ชัน Windows ของคุณ จากนั้นสร้างไฟล์ชื่อ web.config
ในรูทแอปพลิเคชันของคุณโดยมีเนื้อหาดังต่อไปนี้:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Application" stopProcessing="true">
<match url=".*" ignoreCase="false" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
</conditions>
<action type="Rewrite" url="index.php" appendQueryString="true" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
กลับมาที่การเขียนโค้ดกันดีกว่า คุณสามารถประกาศเพจที่ล้าสมัยและเปลี่ยนเส้นทางผู้เยี่ยมชมของคุณไปยังไซต์/เพจอื่น:-
$ f3 -> route ( ' GET|HEAD /obsoletepage ' ,
function ( $ f3 ) {
$ f3 -> reroute ( ' /newpage ' );
}
);
หากมีคนพยายามเข้าถึง URL http://www.example.com/obsoletepage
โดยใช้คำขอ HTTP GET หรือ HEAD เฟรมเวิร์กจะเปลี่ยนเส้นทางผู้ใช้ไปยัง URL: http://www.example.com/newpage
ดังที่แสดงใน ตัวอย่างข้างต้น คุณยังสามารถเปลี่ยนเส้นทางผู้ใช้ไปยังไซต์อื่นได้ เช่น $f3->reroute('http://www.anotherexample.org/');
-
การเปลี่ยนเส้นทางจะมีประโยชน์อย่างยิ่งเมื่อคุณจำเป็นต้องบำรุงรักษาไซต์ของคุณ คุณสามารถมีตัวจัดการเส้นทางที่แจ้งให้ผู้เยี่ยมชมทราบว่าไซต์ของคุณออฟไลน์ในช่วงเวลาสั้นๆ
การเปลี่ยนเส้นทาง HTTP เป็นสิ่งที่ขาดไม่ได้ แต่ก็อาจมีราคาแพงเช่นกัน ให้มากที่สุดเท่าที่จะเป็นไปได้ อย่าใช้ $f3->reroute()
เพื่อส่งผู้ใช้ไปยังหน้าอื่นบนเว็บไซต์เดียวกัน หากคุณสามารถควบคุมโฟลว์ของแอปพลิเคชันของคุณได้โดยการเรียกใช้ฟังก์ชันหรือเมธอดที่จัดการเส้นทางเป้าหมาย อย่างไรก็ตาม วิธีการนี้จะไม่เปลี่ยน URL บนแถบที่อยู่ของเว็บเบราว์เซอร์ของผู้ใช้ หากนี่ไม่ใช่พฤติกรรมที่คุณต้องการและคุณจำเป็นต้องส่งผู้ใช้ไปยังหน้าอื่นจริงๆ ในกรณีเช่นการส่งแบบฟอร์มสำเร็จหรือหลังจากที่ผู้ใช้ได้รับการรับรองความถูกต้องแล้ว Fat-Free จะส่งส่วนหัว HTTP 302 Found
สำหรับความพยายามอื่นๆ ทั้งหมดในการเปลี่ยนเส้นทางไปยังหน้าหรือไซต์อื่น เฟรมเวิร์กจะส่งส่วนหัว HTTP 301 Moved Permanently
ณ รันไทม์ Fat-Free จะสร้างข้อผิดพลาด HTTP 404 โดยอัตโนมัติทุกครั้งที่เห็นว่าคำขอ HTTP ขาเข้าไม่ตรงกับเส้นทางใดๆ ที่กำหนดไว้ในแอปพลิเคชันของคุณ อย่างไรก็ตาม มีหลายครั้งที่คุณจำเป็นต้องกระตุ้นมันด้วยตัวเอง
ยกตัวอย่างเส้นทางที่กำหนดเป็น GET /dogs/@breed
ตรรกะแอปพลิเคชันของคุณอาจเกี่ยวข้องกับการค้นหาฐานข้อมูลและพยายามดึงข้อมูลบันทึกที่สอดคล้องกับค่าของ @breed
ในคำขอ HTTP ขาเข้า เนื่องจาก Fat-Free จะยอมรับค่าใดๆ ที่อยู่หลังคำนำหน้า /dogs/
เนื่องจากมีโทเค็น @breed
การแสดงข้อความ HTTP 404 Not Found
จึงกลายเป็นสิ่งจำเป็นโดยทางโปรแกรมเมื่อโปรแกรมไม่พบรายการที่ตรงกันในฐานข้อมูลของเรา หากต้องการทำเช่นนั้น ให้ใช้คำสั่งต่อไปนี้:-
$ f3 -> error ( 404 );
สถาปัตยกรรมของ Fat-Free ขึ้นอยู่กับแนวคิดที่ว่า HTTP URI เป็นตัวแทนของทรัพยากรเว็บเชิงนามธรรม (ไม่จำกัดเพียง HTML) และทรัพยากรแต่ละรายการสามารถย้ายจากสถานะแอปพลิเคชันหนึ่งไปยังอีกสถานะหนึ่งได้ ด้วยเหตุนี้ F3 จึงไม่มีข้อจำกัดใดๆ เกี่ยวกับวิธีจัดโครงสร้างแอปพลิเคชันของคุณ หากคุณต้องการใช้รูปแบบ Model-View-Controller F3 สามารถช่วยคุณแบ่งส่วนประกอบแอปพลิเคชันของคุณเพื่อให้ยึดตามกระบวนทัศน์นี้ ในทางกลับกัน กรอบงานยังสนับสนุนรูปแบบทรัพยากร-วิธีการ-ตัวแทน และการนำไปปฏิบัติจะตรงไปตรงมามากกว่า
นี่คือตัวอย่างของอินเทอร์เฟซ ReST:-
class Item {
function get () {}
function post () {}
function put () {}
function delete () {}
}
$ f3 = require ( ' lib/base.php ' );
$ f3 -> map ( ' /cart/@item ' , ' Item ' );
$ f3 -> run ();
เมธอด $f3->map()
ของ Fat-Free จัดเตรียมอินเทอร์เฟซ ReST โดยการแมปวิธี HTTP ในเส้นทางไปยังเมธอดที่เทียบเท่าของอ็อบเจ็กต์หรือคลาส PHP หากแอปพลิเคชันของคุณได้รับคำขอ HTTP ขาเข้า เช่น GET /cart/123
Fat-Free จะถ่ายโอนการควบคุมไปยังเมธอด get()
ของอ็อบเจ็กต์หรือคลาสโดยอัตโนมัติ ในทางกลับกัน คำขอ POST /cart/123
จะถูกส่งไปยังเมธอด post()
ของคลาส Item
หมายเหตุ: เบราว์เซอร์ไม่ได้ใช้วิธี HTTP PUT
และ DELETE
ในรูปแบบ HTML ปกติ วิธีการ ReST เหล่านี้และวิธีอื่น ๆ ( HEAD
และ CONNECT
) สามารถเข้าถึงได้ผ่านการเรียก AJAX ไปยังเซิร์ฟเวอร์เท่านั้น
หากเฟรมเวิร์กได้รับการร้องขอ HTTP สำหรับเส้นทางที่แมปกับวิธีที่คลาสไม่ได้ใช้งาน (บางทีคุณอาจทำข้อผิดพลาดในการแมปเส้นทางหรือยังไม่ได้เขียนเมธอด) จะสร้าง HTTP 405 Method Not Allowed
ข้อผิดพลาด HTTP 405 Method Not Allowed
หากไคลเอนต์ร้องขอ HTTP OPTIONS
สำหรับทรัพยากร URL F3 จะตอบสนองด้วยส่วนหัว HTTP ที่เหมาะสมซึ่งระบุว่าวิธีการใดที่ได้รับอนุญาตสำหรับทรัพยากร (HEAD, GET, PUT ฯลฯ) กรอบงานจะไม่แมปคำขอ OPTIONS
กับคลาส
Fat-Free มีวิธีโหลดคลาสเฉพาะในเวลาที่คุณต้องการเท่านั้น ดังนั้นจึงไม่กินหน่วยความจำมากเกินกว่าส่วนใดส่วนหนึ่งของแอปพลิเคชันของคุณต้องการ และคุณไม่จำเป็นต้องเขียนรายการคำ include
หรือ require
คำสั่งยาวๆ เพียงเพื่อโหลดคลาส PHP ที่บันทึกไว้ในไฟล์ต่างๆ และตำแหน่งที่แตกต่างกัน กรอบงานสามารถทำสิ่งนี้ให้คุณได้โดยอัตโนมัติ เพียงบันทึกไฟล์ของคุณ (หนึ่งคลาสต่อไฟล์) ในโฟลเดอร์และบอกให้เฟรมเวิร์กโหลดไฟล์ที่เหมาะสมโดยอัตโนมัติเมื่อคุณเรียกใช้เมธอดในคลาส: -
$ f3 -> set ( ' AUTOLOAD ' , ' autoload/ ' );
คุณสามารถกำหนดตำแหน่งอื่นสำหรับคลาสที่โหลดอัตโนมัติของคุณได้โดยการเปลี่ยนค่าของตัวแปรโกลบอล AUTOLOAD
คุณยังสามารถมีเส้นทางโหลดอัตโนมัติได้หลายเส้นทาง หากคุณมีคลาสที่จัดระเบียบและอยู่ในโฟลเดอร์ที่แตกต่างกัน คุณสามารถสั่งให้เฟรมเวิร์กโหลดคลาสที่เหมาะสมโดยอัตโนมัติเมื่อมีการเรียกใช้เมธอดแบบสแตติกหรือเมื่อออบเจ็กต์ถูกสร้างอินสแตนซ์ แก้ไขตัวแปร AUTOLOAD
ด้วยวิธีนี้:-
$ f3 -> set ( ' AUTOLOAD ' , ' admin/autoload/; user/autoload/; default/ ' );
สิ่งสำคัญ: ยกเว้นนามสกุล .php ชื่อคลาสและชื่อไฟล์จะต้องเหมือนกัน เพื่อให้เฟรมเวิร์กโหลดคลาสของคุณโดยอัตโนมัติอย่างถูกต้อง ชื่อพื้นฐานของไฟล์นี้จะต้องเหมือนกันกับการเรียกใช้คลาสของคุณ เช่น F3 จะค้นหา Foo/BarBaz.php
หรือ foo/barbaz.php
เมื่อตรวจพบคำสั่ง new FooBarBaz
ในแอปพลิเคชันของคุณ
AUTOLOAD
อนุญาตให้ลำดับชั้นของคลาสอยู่ในโฟลเดอร์ย่อยที่มีชื่อคล้ายกัน ดังนั้น หากคุณต้องการให้เฟรมเวิร์กโหลดคลาสเนมสเปซที่ถูกเรียกใช้ในลักษณะต่อไปนี้:-
$ f3 -> set ( ' AUTOLOAD ' , ' autoload/ ' );
$ obj = new Gadgets iPad ;
คุณสามารถสร้างลำดับชั้นโฟลเดอร์ที่เป็นไปตามโครงสร้างเดียวกันได้ สมมติว่า /var/www/html/
เป็นรูทเว็บของคุณ จากนั้น F3 จะค้นหาคลาสใน /var/www/html/autoload/gadgets/ipad.php
ไฟล์ ipad.php
ควรมีโค้ดขั้นต่ำดังต่อไปนี้:-
namespace Gadgets ;
class iPad {}
ข้อควรจำ: ชื่อไดเรกทอรีทั้งหมดใน Fat-Free จะต้องลงท้ายด้วยเครื่องหมายทับ คุณสามารถกำหนดเส้นทางการค้นหาสำหรับตัวโหลดอัตโนมัติได้ดังนี้:-
$ f3 -> set ( ' AUTOLOAD ' , ' main/;aux/ ' );
F3 ซึ่งเป็นเฟรมเวิร์กที่รับรู้เนมสเปซ ช่วยให้คุณใช้เมธอดในคลาสเนมสเปซเป็นตัวจัดการเส้นทางได้ และมีหลายวิธีในการทำเช่นนี้ หากต้องการเรียกวิธีการคงที่: -
$ f3 -> set ( ' AUTOLOAD ' , ' classes/ ' );
$ f3 -> route ( ' GET|POST / ' , ' MainHome::show ' );
โค้ดด้านบนจะเรียกใช้เมธอด static show()
ของคลาส Home
ภายในเนมสเปซ Main
คลาส Home
จะต้องถูกบันทึกไว้ในโฟลเดอร์ classes/main/home.php
เพื่อให้โหลดโดยอัตโนมัติ
หากคุณต้องการทำงานกับวัตถุ:-
$ f3 -> route ( ' GET|POST / ' , ' MainHome->show ' );
จะสร้างอินสแตนซ์คลาส Home
ณ รันไทม์และเรียกใช้เมธอด show()
หลังจากนั้น
F3 มี Listener เหตุการณ์การกำหนดเส้นทางสองสามตัวที่อาจช่วยคุณปรับปรุงโฟลว์และโครงสร้างของคลาสคอนโทรลเลอร์ สมมติว่าคุณมีเส้นทางที่กำหนดไว้ดังนี้:-
$ f3 -> route ( ' GET / ' , ' Main->home ' );
หากแอปพลิเคชันได้รับการร้องขอ HTTP ที่ตรงกับเส้นทางข้างต้น F3 จะสร้างอินสแตนซ์ Main
แต่ก่อนที่จะดำเนินการเมธอด home()
เฟรมเวิร์กจะค้นหาเมธอดในคลาสนี้ชื่อ beforeRoute()
ในกรณีที่พบ F3 จะรันโค้ดที่มีอยู่ในตัวจัดการเหตุการณ์ beforeRoute()
ก่อนที่จะถ่ายโอนการควบคุมไปยังเมธอด home()
เมื่อเสร็จสิ้นแล้ว กรอบงานจะค้นหาตัวจัดการเหตุการณ์ afterRoute()
เช่นเดียวกับ beforeRoute()
วิธีการจะถูกดำเนินการหากมีการกำหนดไว้
นี่คือสินค้า F3 อีกอัน:-
$ f3 -> route ( ' GET /products/@action ' , ' Products->@action ' );
หากแอปพลิเคชันของคุณได้รับการร้องขอ เช่น /products/itemize
F3 จะแยกสตริง 'itemize'
ออกจาก URL และส่งต่อไปยังโทเค็น @action
ในตัวจัดการเส้นทาง F3 จะค้นหาคลาสชื่อ Products
และดำเนินการเมธอด itemize()
ตัวจัดการเส้นทางแบบไดนามิกอาจมีรูปแบบต่างๆ:-
// static method
$ f3 -> route ( ' GET /public/@genre ' , ' Main::@genre ' );
// object mode
$ f3 -> route ( ' GET /public/@controller/@action ' , ' @controller->@action ' );
F3 ก่อให้เกิดข้อผิดพลาด HTTP 404 Not Found
ขณะรันไทม์ หากไม่สามารถถ่ายโอนการควบคุมไปยังคลาสหรือเมธอดที่เกี่ยวข้องกับเส้นทางปัจจุบัน เช่น คลาสหรือเมธอดที่ไม่ได้กำหนด
รูปแบบการกำหนดเส้นทางอาจมีตัวดัดแปลงที่กำหนดให้กรอบงานตัดสินใจกำหนดเส้นทางตามประเภทของคำขอ HTTP: -
$ f3 -> route ( ' GET /example [ajax] ' , ' Page->getFragment ' );
$ f3 -> route ( ' GET /example [sync] ' , ' Page->getFull ' );
คำสั่งแรกจะกำหนดเส้นทางคำขอ HTTP ไปยังการเรียกกลับ Page->getFragment()
เฉพาะในกรณีที่เซิร์ฟเวอร์ได้รับส่วนหัว X-Requested-With: XMLHttpRequest
(วัตถุ AJAX) หากตรวจพบคำขอทั่วไป (ซิงโครนัส) F3 จะเลื่อนลงไปที่รูปแบบการจับคู่ถัดไป และในกรณีนี้จะดำเนินการเรียกกลับ Page->getFull()
หากไม่มีการกำหนดตัวแก้ไขในรูปแบบการกำหนดเส้นทาง ทั้งประเภทคำขอ AJAX และซิงโครนัสจะถูกกำหนดเส้นทางไปยังตัวจัดการที่ระบุ
ตัวแก้ไขรูปแบบเส้นทางยังเป็นที่รู้จักโดย $f3->map()
ตัวแปรที่กำหนดใน Fat-Free เป็นตัวแปรส่วนกลาง กล่าวคือ ตัวแปรเหล่านี้สามารถเข้าถึงได้โดยองค์ประกอบ MVC ใดๆ Framework Globals ไม่เหมือนกับ PHP Globals content
ที่มีชื่อตัวแปร F3 ไม่เหมือนกับ $content
ของ PHP F3 เป็นภาษาเฉพาะโดเมนในสิทธิของตนเองและรักษาตารางสัญลักษณ์แยกต่างหากสำหรับตัวแปรระบบและแอปพลิเคชัน กรอบงานก็เหมือนกับโปรแกรมเชิงวัตถุที่ออกแบบมาอย่างดีทุกตัว ไม่ทำให้เนมสเปซโกลบอล PHP เสียหายด้วยค่าคงที่ ตัวแปร ฟังก์ชันหรือคลาสที่อาจขัดแย้งกับแอปพลิเคชันใดๆ ไม่เหมือนกับเฟรมเวิร์กอื่นๆ F3 ไม่ได้ใช้คำสั่ง define()
ของ PHP ค่าคงที่ของเฟรมเวิร์กทั้งหมดถูกจำกัดอยู่ในคลาส
ในการกำหนดค่าให้กับตัวแปรไร้ไขมัน:
$ f3 -> set ( ' var ' ,value); // or
$ f3 -> var =value;
$ f3 -> set ( ' hello.world ' , ' good morning ' ); // translates to : 'hello' == array ( 'world' = > 'good morning' )
$ f3 ->{ ' hello.world ' }= ' good morning ' ; // same as prior statement
หมายเหตุ: ตัวแปร Fat-Free ยอมรับข้อมูล PHP ทุกประเภท รวมถึงอ็อบเจ็กต์และฟังก์ชันที่ไม่ระบุชื่อ
วิธีตั้งค่าตัวแปรหลายตัวพร้อมกัน:
$ f3 -> mset (
[
' foo ' => ' bar ' ,
' baz ' => 123
]
);
เพื่อดึงค่าของตัวแปรกรอบงานชื่อ var
:-
echo $ f3 -> get ( ' var ' ); // or
echo $ f3 -> var ;
หากต้องการลบตัวแปร Fat-Free ออกจากหน่วยความจำหากคุณไม่ต้องการมันอีกต่อไป (ทิ้งไปเพื่อไม่ให้รบกวนฟังก์ชัน/วิธีการอื่น ๆ ของคุณ) ให้ใช้วิธีการ:-
$ f3 -> clear ( ' var ' ); // or
unset( $ f3 -> var );
หากต้องการทราบว่าตัวแปรถูกกำหนดไว้ก่อนหน้านี้หรือไม่:-
$ f3 -> exists ( ' var ' ) //
isset ( $ f3 -> var )
F3 มีตารางสัญลักษณ์ของตัวเองสำหรับตัวแปรเฟรมเวิร์กและแอปพลิเคชัน ซึ่งไม่ขึ้นอยู่กับ PHP ตัวแปรบางตัวถูกแมปกับ PHP globals SESSION
ของ Fat-Free เทียบเท่ากับ $_SESSION
และ REQUEST
แมปกับ $_REQUEST
แนะนำให้ใช้ตัวแปรเฟรมเวิร์กแทน PHP เพื่อช่วยคุณในการถ่ายโอนข้อมูลผ่านฟังก์ชัน คลาส และวิธีการต่างๆ พวกเขายังมีข้อดีอื่น ๆ :-
SESSION
ก็เปลี่ยน $_SESSION
พื้นฐานของ PHP ด้วย การเปลี่ยนแปลงอย่างหลังยังเปลี่ยนแปลงคู่ของกรอบงานด้วย Fat-Free ไม่ได้เป็นเพียงพื้นที่เก็บข้อมูลโง่ๆ สำหรับตัวแปรและค่าของมันเท่านั้น นอกจากนี้ยังสามารถจัดการเซสชันและสิ่งอื่น ๆ โดยอัตโนมัติ การกำหนดหรือการดึงค่าผ่านตัวแปร SESSION
ของ F3 จะเป็นการเริ่มเซสชันโดยอัตโนมัติ หากคุณใช้ $_SESSION
(หรือฟังก์ชันที่เกี่ยวข้องกับเซสชัน) โดยตรง แทนที่จะเป็นตัวแปรเฟรมเวิร์ก SESSION
แอปพลิเคชันของคุณจะรับผิดชอบในการจัดการเซสชัน
ตามกฎแล้ว ตัวแปรเฟรมเวิร์กจะไม่คงอยู่ระหว่างคำขอ HTTP เฉพาะ SESSION
และ COOKIE
(และองค์ประกอบ) ที่ถูกแมปกับตัวแปรโกลบอล $_SESSION
และ $_COOKIE
ของ PHP เท่านั้นที่ได้รับการยกเว้นจากลักษณะไร้สถานะของ HTTP
มีตัวแปรส่วนกลางที่กำหนดไว้ล่วงหน้าหลายตัวที่ใช้ภายในโดย Fat-Free และคุณสามารถใช้ตัวแปรเหล่านี้ในแอปพลิเคชันของคุณได้อย่างแน่นอน ให้แน่ใจว่าคุณรู้ว่าคุณกำลังทำอะไรอยู่ การเปลี่ยนแปลงตัวแปรโกลบอลที่ไร้ไขมันบางตัวอาจส่งผลให้เกิดพฤติกรรมของเฟรมเวิร์กที่ไม่คาดคิด
เฟรมเวิร์กมีตัวแปรหลายตัวเพื่อช่วยให้คุณจัดระเบียบไฟล์และไดเร็กทอรีของคุณ เราได้เห็นแล้วว่าเราสามารถทำให้การโหลดคลาสอัตโนมัติโดยใช้ AUTOLOAD
มีตัวแปรส่วนกลาง UI
ซึ่งมีเส้นทางที่ชี้ไปยังตำแหน่งของมุมมอง/เทมเพลต HTML ของคุณ DEBUG
เป็นอีกหนึ่งตัวแปรที่คุณจะใช้ค่อนข้างบ่อยในระหว่างการพัฒนาแอปพลิเคชัน และใช้สำหรับตั้งค่ารายละเอียดการติดตามข้อผิดพลาด
โปรดดูการอ้างอิงด่วน หากคุณต้องการรายการตัวแปรเฟรมเวิร์กในตัวที่ครอบคลุม
ตัวแปรเฟรมเวิร์กอาจมีตัวอักษร ตัวเลข และขีดล่างจำนวนเท่าใดก็ได้ ต้องขึ้นต้นด้วยอักขระอัลฟาและไม่ควรเว้นวรรค ชื่อตัวแปรต้องตรงตามตัวพิมพ์ใหญ่-เล็ก
F3 ใช้ตัวพิมพ์ใหญ่ทั้งหมดสำหรับตัวแปรส่วนกลางที่กำหนดไว้ล่วงหน้าภายใน ไม่มีอะไรหยุดคุณจากการใช้ชื่อตัวแปรที่ประกอบด้วยตัวพิมพ์ใหญ่ทั้งหมดในโปรแกรมของคุณเอง แต่โดยทั่วไปแล้ว ให้ยึดตัวพิมพ์เล็ก (หรือ CamelCase) เมื่อคุณตั้งค่าตัวแปรของคุณเอง เพื่อหลีกเลี่ยงความขัดแย้งที่อาจเกิดขึ้นกับการเปิดตัวเฟรมเวิร์กในปัจจุบันและอนาคต .
คุณไม่ควรใช้คำที่สงวนไว้สำหรับ PHP เช่น if
, for
, class
, default
ฯลฯ เป็นชื่อตัวแปรเฟรมเวิร์ก สิ่งเหล่านี้อาจทำให้เกิดผลลัพธ์ที่คาดเดาไม่ได้
F3 ยังมีเครื่องมือมากมายที่จะช่วยคุณในเรื่องตัวแปรเฟรมเวิร์ก
$ f3 -> set ( ' a ' , ' fire ' );
$ f3 -> concat ( ' a ' , ' cracker ' );
echo $ f3 -> get ( ' a ' ); // returns the string 'firecracker'
$ f3 -> copy ( ' a ' , ' b ' );
echo $ f3 -> get ( ' b ' ); // returns the same string : 'firecracker'
F3 ยังมีวิธีการดั้งเดิมสำหรับการทำงานกับตัวแปรอาเรย์: -
$ f3 -> set ( ' colors ' ,[ ' red ' , ' blue ' , ' yellow ' ]);
$ f3 -> push ( ' colors ' , ' green ' ); // works like PHP ' s array_push ()
echo $ f3 -> pop ( ' colors ' ); // returns 'green'
$ f3 -> unshift ( ' colors ' , ' purple ' ); // similar to array_unshift ()
echo $ f3 -> shift ( ' colors ' ); // returns 'purple'
$ f3 -> set ( ' grays ' ,[ ' light ' , ' dark ' ]);
$ result = $ f3 -> merge ( ' colors ' , ' grays ' ); // merges the two arrays
ต่างจากเฟรมเวิร์กอื่นๆ ที่มีโครงสร้างโฟลเดอร์ที่เข้มงวด F3 ให้ความยืดหยุ่นอย่างมากแก่คุณ คุณสามารถมีโครงสร้างโฟลเดอร์ที่มีลักษณะเช่นนี้ (คำในวงเล็บในตัวพิมพ์ใหญ่ทั้งหมดแสดงถึงตัวแปรเฟรมเวิร์ก F3 ที่ต้องปรับแต่ง): -
/ (your Web root, where index.php is located)
app/ (application files)
dict/ (LOCALES, optional)
controllers/
logs/ (LOGS, optional)
models/
views/ (UI)
css/
js/
lib/ (you can store base.php here)
tmp/ (TEMP, used by the framework)
cache/ (CACHE)
คุณสามารถจัดระเบียบไฟล์และไดเร็กทอรีของคุณได้ตามที่คุณต้องการ เพียงตั้งค่าตัวแปรส่วนกลาง F3 ที่เหมาะสม หากคุณต้องการไซต์ที่ปลอดภัยจริงๆ Fat-Free ยังช่วยให้คุณจัดเก็บไฟล์ทั้งหมดของคุณในไดเร็กทอรีที่ไม่สามารถเข้าถึงเว็บได้ ข้อกำหนดเพียงอย่างเดียวคือคุณต้องปล่อยให้ index.php
, .htaccess
และไฟล์สาธารณะของคุณ เช่น CSS, JavaScript, รูปภาพ ฯลฯ อยู่ในเส้นทางที่เบราว์เซอร์ของคุณมองเห็นได้
Fat-Free สร้างหน้าแสดงข้อผิดพลาด HTML ของตัวเอง พร้อมด้วยการติดตามสแต็กเพื่อช่วยคุณในการดีบัก นี่คือตัวอย่าง:-
ข้อผิดพลาดเซิร์ฟเวอร์ภายใน
strpos() ต้องการอย่างน้อย 2 พารามิเตอร์ โดยให้ 0
• var/html/dev/main.php:96 strpos() • var/html/dev/index.php:16 Base->run()
หากคุณรู้สึกว่ามันดูธรรมดาเกินไปหรือต้องการทำสิ่งอื่นเมื่อเกิดข้อผิดพลาด คุณสามารถสร้างตัวจัดการข้อผิดพลาดที่คุณกำหนดเองได้:-
$ f3 -> set ( ' ONERROR ' ,
function ( $ f3 ) {
// custom error handler code goes here
// use this if you want to display errors in a
// format consistent with your site ' s theme
echo $ f3 -> get ( ' ERROR.status ' );
}
);
F3 รักษาตัวแปรส่วนกลางที่มีรายละเอียดของข้อผิดพลาดล่าสุดที่เกิดขึ้นในแอปพลิเคชันของคุณ ตัวแปร ERROR
เป็นอาร์เรย์ที่มีโครงสร้างดังนี้:-
ERROR.code - displays the error code (404, 500, etc.)
ERROR.status - header and page title
ERROR.text - error context
ERROR.trace - stack trace
ในขณะที่พัฒนาแอปพลิเคชันของคุณ ทางที่ดีควรตั้งค่าระดับการแก้ไขข้อบกพร่องเป็นระดับสูงสุด เพื่อให้คุณสามารถติดตามข้อผิดพลาดทั้งหมดไปยังสาเหตุที่แท้จริง:-
$ f3 -> set ( ' DEBUG ' , 3 );
เพียงแทรกคำสั่งในลำดับบูตสแตรปของแอปพลิเคชันของคุณ
เมื่อใบสมัครของคุณพร้อมสำหรับการเปิดตัว เพียงลบใบแจ้งยอดออกจากใบสมัครของคุณ หรือแทนที่ด้วย:-
$ f3 -> set ( ' DEBUG ' , 0 );
วิธีนี้จะระงับเอาต์พุตการติดตามสแต็กในหน้าข้อผิดพลาด HTML ที่ระบบสร้างขึ้น (เนื่องจากผู้เยี่ยมชมเว็บไซต์ของคุณไม่ได้ตั้งใจให้มองเห็น)
DEBUG
สามารถมีค่าได้ตั้งแต่ 0 (ระงับการติดตามสแต็ก) ถึง 3 (รายละเอียดส่วนใหญ่)
อย่าลืม! การติดตามสแต็กอาจมีเส้นทาง ชื่อไฟล์ คำสั่งฐานข้อมูล ชื่อผู้ใช้ และรหัสผ่าน คุณอาจเปิดเผยเว็บไซต์ของคุณให้มีความเสี่ยงด้านความปลอดภัยที่ไม่จำเป็น หากคุณล้มเหลวในการตั้งค่าตัวแปรส่วนกลาง DEBUG
เป็น 0 ในสภาพแวดล้อมการใช้งานจริง
หากแอปพลิเคชันของคุณจำเป็นต้องกำหนดค่าโดยผู้ใช้ได้ F3 มีวิธีที่สะดวกในการอ่านไฟล์การกำหนดค่าเพื่อตั้งค่าแอปพลิเคชันของคุณ ด้วยวิธีนี้ คุณและผู้ใช้จะสามารถปรับแต่งแอปพลิเคชันได้โดยไม่ต้องแก้ไขโค้ด PHP ใดๆ
แทนที่จะสร้างสคริปต์ PHP ที่มีโค้ดตัวอย่างต่อไปนี้:-
$ f3 -> set ( ' num ' , 123 );
$ f3 -> set ( ' str ' , ' abc ' );
$ f3 -> set ( ' hash ' ,[ ' x ' => 1 , ' y ' => 2 , ' z ' => 3 ]);
$ f3 -> set ( ' items ' ,[ 7 , 8 , 9 ]);
$ f3 -> set ( ' mix ' ,[ ' this ' , 123.45 , FALSE ]);
คุณสามารถสร้างไฟล์กำหนดค่าที่ทำสิ่งเดียวกัน:-
[globals]
num =123
; this is a regular string
str =abc
; another way of assigning strings
str = " abc "
; this is an array
hash[x]=1
hash[y]=2
hash[z]=3
; dot-notation is recognized too
hash.x =1
hash.y =2
hash.z =3
; this is also an array
items =7,8,9
; array with mixed elements
mix = " this " ,123.45,FALSE
แทนที่จะใช้คำสั่ง $f3->set()
ที่มีความยาวในโค้ดของคุณ คุณสามารถสั่งให้เฟรมเวิร์กโหลดไฟล์การกำหนดค่าเพื่อทดแทนโค้ดได้ มาบันทึกข้อความด้านบนเป็น setup.cfg กันดีกว่า เราก็สามารถเรียกมันได้โดยง่าย:-
$ f3 -> config ( ' setup.cfg ' );
ค่าสตริงไม่จำเป็นต้องใส่เครื่องหมายคำพูด เว้นแต่คุณต้องการให้มีช่องว่างนำหน้าหรือต่อท้ายรวมอยู่ด้วย หากควรใช้เครื่องหมายจุลภาคเป็นส่วนหนึ่งของสตริง ให้ล้อมสตริงโดยใช้เครื่องหมายคำพูดคู่ - มิฉะนั้น ค่าจะถือเป็นอาร์เรย์ (เครื่องหมายจุลภาคจะใช้เป็นตัวคั่นองค์ประกอบอาร์เรย์) สตริงสามารถขยายได้หลายบรรทัด:-
[globals]
str = " this is a
very long
string "
F3 ยังช่วยให้คุณสามารถกำหนดเส้นทาง HTTP ในไฟล์กำหนดค่า: -
[routes]
GET /=home
GET / 404 =App->page404
GET /page/@ num =Page->@controller
แผนที่เส้นทางสามารถกำหนดได้ในไฟล์กำหนดค่าด้วย: -
[maps]
/ blog =BlogLogin
/blog/@ controller =Blog@controller
จำเป็นต้องมีส่วนหัวของส่วน [globals]
, [routes]
และ [maps]
คุณสามารถรวมทั้งสองส่วนไว้ในไฟล์กำหนดค่าไฟล์เดียวได้ แม้ว่าจะแนะนำให้มี [routes]
และ [maps]
ในไฟล์แยกกันก็ตาม วิธีนี้ทำให้คุณสามารถอนุญาตให้ผู้ใช้แก้ไขแฟล็กเฉพาะแอปพลิเคชันบางอย่างได้ และในขณะเดียวกันก็จำกัดไม่ให้ผู้ใช้เข้าไปยุ่งกับลอจิกการกำหนดเส้นทางของคุณ
อินเทอร์เฟซผู้ใช้ เช่น หน้า HTML ควรเป็นอิสระจากโค้ด PHP ที่เกี่ยวข้องกับการกำหนดเส้นทางและตรรกะทางธุรกิจ นี่เป็นพื้นฐานของกระบวนทัศน์ MVC การแก้ไขขั้นพื้นฐาน เช่น การแปลง <h3>
เป็น <p>
ไม่ควรเรียกร้องให้มีการเปลี่ยนแปลงรหัสแอปพลิเคชันของคุณ ในลักษณะเดียวกัน การเปลี่ยนเส้นทางง่ายๆ เช่น GET /about
เป็น GET /about-us
ไม่ควรมีผลกระทบใดๆ ต่ออินเทอร์เฟซผู้ใช้และตรรกะทางธุรกิจของคุณ (มุมมองและโมเดลใน MVC หรือการเป็นตัวแทนและวิธีการใน RMR)
การผสมการเขียนโปรแกรมและส่วนประกอบส่วนต่อประสานผู้ใช้ในไฟล์เดียวเช่นการเข้ารหัสสปาเก็ตตี้ทำให้การบำรุงรักษาแอปพลิเคชันในอนาคตเป็นฝันร้าย
F3 รองรับ PHP เป็นเอ็นจิ้นเทมเพลต ดูที่ชิ้นส่วน HTML นี้บันทึกเป็น template.htm
:-
< p > Hello, < ?php echo $name; ? > ! </ p >
หากเปิดใช้งานแท็กสั้น ๆ บนเซิร์ฟเวอร์ของคุณสิ่งนี้ควรใช้งานได้เช่นกัน:-
< p > Hello, < ?= $name ? > </ p >
ในการแสดงเทมเพลตนี้คุณสามารถมีรหัส PHP ที่มีลักษณะเช่นนี้ (เก็บไว้ในไฟล์แยกจากเทมเพลต):-
$ f3 = require ( ' lib/base.php ' );
$ f3 -> route ( ' GET / ' ,
function ( $ f3 ) {
$ f3 -> set ( ' name ' , ' world ' );
$ view = new View ;
echo $ view -> render ( ' template.htm ' );
// Previous two lines can be shortened to : -
// echo View :: instance () - > render ( 'template.htm' );
}
);
$ f3 -> run ();
ปัญหาเพียงอย่างเดียวของการใช้ PHP เป็นเอ็นจิ้นเทมเพลตเนื่องจากรหัส PHP แบบฝังในไฟล์เหล่านี้เป็นความพยายามอย่างมีสติที่จำเป็นในการยึดติดกับแนวทางในการแยกข้อกังวลและต่อต้านการล่อลวงของการผสมตรรกะทางธุรกิจกับส่วนต่อประสานผู้ใช้ของคุณ
เป็นทางเลือกแทน PHP คุณสามารถใช้เอ็นจิ้นเทมเพลตของ F3 ได้ ชิ้นส่วน HTML ข้างต้นสามารถเขียนใหม่เป็น:-
< p > Hello, {{ @name }}! </ p >
และรหัสที่จำเป็นในการดูเทมเพลตนี้:-
$ f3 = require ( ' lib/base.php ' );
$ f3 -> route ( ' GET / ' ,
function ( $ f3 ) {
$ f3 -> set ( ' name ' , ' world ' );
$ template = new Template ;
echo $ template -> render ( ' template.htm ' );
// Above lines can be written as : -
// echo Template :: instance () - > render ( 'template.htm' );
}
);
$ f3 -> run ();
เช่นเดียวกับโทเค็นการกำหนดเส้นทางที่ใช้ในการจับตัวแปรใน URL (ยังจำตัวอย่าง GET /brew/@count
ในส่วนก่อนหน้านี้ได้หรือไม่) โทเค็นเทมเพลต F3 เริ่มต้นด้วยสัญลักษณ์ @
ตามด้วยชุดตัวอักษรและตัวเลขที่ล้อมรอบด้วยการจัดฟัน ตัวละครตัวแรกจะต้องเป็นอัลฟ่า โทเค็นเทมเพลตมีการติดต่อแบบหนึ่งต่อหนึ่งกับตัวแปรเฟรมเวิร์ก เฟรมเวิร์กจะแทนที่โทเค็นโดยอัตโนมัติด้วยค่าที่เก็บไว้ในตัวแปรที่มีชื่อเดียวกัน
ในตัวอย่างของเรา F3 แทนที่โทเค็น @name
ในเทมเพลตของเราด้วยค่าที่เรากำหนดให้กับตัวแปรชื่อ ที่รันไทม์เอาต์พุตของรหัสด้านบนจะเป็น:-
< p > Hello, world </ p >
กังวลเกี่ยวกับประสิทธิภาพของเทมเพลต F3 หรือไม่? ที่รันไทม์เฟรมเวิร์กวิเคราะห์และรวบรวม/แปลงเทมเพลต F3 เป็นรหัส PHP ในครั้งแรกที่แสดงผ่าน $template->render()
เฟรมเวิร์กจะใช้รหัสที่รวบรวมนี้ในการโทรที่ตามมาทั้งหมด ดังนั้นประสิทธิภาพควรจะเหมือนกับเทมเพลต PHP หากไม่ดีขึ้นเนื่องจากการเพิ่มประสิทธิภาพของรหัสโดยคอมไพเลอร์เทมเพลตเมื่อมีเทมเพลตที่ซับซ้อนมากขึ้น
ไม่ว่าคุณจะใช้เอ็นจิ้นเทมเพลตของ PHP หรือ F3 ของตัวเองการเรนเดอร์เทมเพลตอาจเร็วขึ้นอย่างมากหากคุณมี APC, Wincache หรือ XCache บนเซิร์ฟเวอร์ของคุณ
ดังที่ได้กล่าวไว้ก่อนหน้านี้ตัวแปรเฟรมเวิร์กสามารถถือประเภทข้อมูล PHP ใด ๆ อย่างไรก็ตามการใช้ประเภทข้อมูลที่ไม่ใช่สการ์ในเทมเพลต F3 อาจให้ผลลัพธ์ที่แปลกหากคุณไม่ระวัง นิพจน์ในการจัดฟันแบบหยิกจะได้รับการประเมินและแปลงเป็นสตริงเสมอ คุณควร จำกัด ตัวแปรอินเทอร์เฟซผู้ใช้ของคุณเป็นสเกลาร์ง่าย ๆ :- string
, integer
, boolean
หรือชนิดข้อมูล float
แต่อาร์เรย์ล่ะ? ปลอดไขมันรับรู้อาร์เรย์และคุณสามารถใช้มันในแม่แบบของคุณ คุณสามารถมีบางอย่างเช่น:-
< p > {{ @buddy[0] }}, {{ @buddy[1] }}, and {{ @buddy[2] }} </ p >
และเติมอาร์เรย์ @buddy
ในรหัส PHP ของคุณก่อนเสิร์ฟเทมเพลต:-
$ f3 -> set ( ' buddy ' ,[ ' Tom ' , ' Dick ' , ' Harry ' ]);
อย่างไรก็ตามหากคุณเพียงแค่แทรก {{ @buddy }}
ในเทมเพลตของคุณ PHP จะแทนที่ด้วย 'Array'
เพราะมันแปลงโทเค็นเป็นสตริง ในทางกลับกัน PHP จะสร้าง Array to string conversion
ที่รันไทม์
F3 ช่วยให้คุณสามารถฝังนิพจน์ในเทมเพลต การแสดงออกเหล่านี้อาจใช้ในรูปแบบต่าง ๆ เช่นการคำนวณทางคณิตศาสตร์การแสดงออกของบูลีนค่าคงที่ PHP ฯลฯ นี่คือตัวอย่างบางส่วน:-
{{ 2*(@page-1) }}
{{ (int)765.29+1.2e3 }}
< option value =" F " {{ @active? 'selected=" selected "':'' }} > Female </ option >
{{ var_dump(@xyz) }}
< p > That is {{ preg_match('/Yes/i',@response)?'correct':'wrong' }}! </ p >
{{ @obj- > property }}
หมายเหตุเพิ่มเติมเกี่ยวกับการแสดงออกของอาร์เรย์: โปรดทราบว่า @foo.@bar
เป็นสตริงการเชื่อมต่อ $foo.$bar
) ในขณะที่ @foo.bar
แปลเป็น $foo['bar']
ถ้า $foo[$bar]
เป็นสิ่งที่คุณตั้งใจใช้ @foo[@bar]
สัญกรณ์ปกติ
ตัวแปรเฟรมเวิร์กอาจมีฟังก์ชั่นที่ไม่ระบุชื่อ:
$ f3 -> set ( ' func ' ,
function ( $ a , $ b ) {
return $ a . ' , ' . $ b ;
}
);
เอ็นจิ้นเทมเพลต F3 จะตีความโทเค็นตามที่คาดไว้หากคุณระบุนิพจน์ต่อไปนี้:
{{ @func('hello','world') }}
การทดแทนตัวแปรอย่างง่ายเป็นสิ่งหนึ่งที่เอ็นจิ้นเทมเพลตทั้งหมดมี ปราศจากไขมันมีแขนเสื้อมากขึ้น:-
< include href =" header.htm " />
คำสั่งจะฝังเนื้อหาของเทมเพลตส่วนหัว htm ที่ตำแหน่งที่แน่นอนซึ่งมีการระบุคำสั่ง นอกจากนี้คุณยังสามารถมีเนื้อหาแบบไดนามิกในรูปแบบของ:-
< include href =" {{ @content }} " />
การใช้งานจริงสำหรับคำสั่งเทมเพลตดังกล่าวคือเมื่อคุณมีหลายหน้าด้วยเค้าโครง HTML ทั่วไป แต่มีเนื้อหาที่แตกต่างกัน การสอนเฟรมเวิร์กเพื่อแทรกเทมเพลตย่อยลงในเทมเพลตหลักของคุณนั้นง่ายพอ ๆ กับการเขียนรหัส PHP ต่อไปนี้:-
// switch content to your blog sub - template
$ f3 -> set ( ' content ' , ' blog.htm ' );
// in another route , switch content to the wiki sub - template
$ f3 -> set ( ' content ' , ' wiki.htm ' );
เทมเพลตย่อยอาจมีจำนวนคำสั่งใด ๆ F3 อนุญาตให้เทมเพลตซ้อนกันไม่ จำกัด
คุณสามารถระบุชื่อไฟล์ที่มีส่วนขยายไฟล์. htm หรือ. html แต่มันง่ายกว่าที่จะดูตัวอย่างในเว็บเบราว์เซอร์ของคุณในระหว่างการพัฒนาและการดีบัก เอ็นจิ้นเทมเพลตไม่ จำกัด เฉพาะการแสดงผลไฟล์ HTML ในความเป็นจริงคุณสามารถใช้เอ็นจิ้นเทมเพลตเพื่อแสดงไฟล์ประเภทอื่น ๆ
Directive <include>
ถึงยังมีแอ็ตทริบิวต์เป็นทางเลือก if
คุณสามารถระบุเงื่อนไขที่ต้องได้รับความพึงพอใจก่อนที่จะแทรกเทมเพลตย่อย:-
< include if =" {{ count(@items) }} " href =" items.htm " />
ในระหว่างการเขียน/ดีบั๊กโปรแกรมที่ขับเคลื่อนด้วย F3 และเทมเพลตการออกแบบอาจมีกรณีที่ปิดการแสดงผลของบล็อกของ HTML อาจมีประโยชน์ คุณสามารถใช้คำสั่ง <exclude>
เพื่อจุดประสงค์นี้:-
< exclude >
< p > A chunk of HTML we don't want displayed at the moment </ p >
</ exclude >
นั่นเหมือนกับ <!-- comment -->
แท็กความคิดเห็น html แต่คำสั่ง <exclude>
ทำให้บล็อก HTML มองไม่เห็นโดยสิ้นเชิงเมื่อเทมเพลตถูกแสดงผล
นี่เป็นอีกวิธีหนึ่งในการยกเว้นเนื้อหาเทมเพลตหรือเพิ่มความคิดเห็น:-
{* < p > A chunk of HTML we don't want displayed at the moment </ p > *}
คุณลักษณะเทมเพลตที่มีประโยชน์อีกอย่างหนึ่งคือคำสั่ง <check>
ช่วยให้คุณสามารถฝังชิ้นส่วน HTML ขึ้นอยู่กับการประเมินเงื่อนไขที่แน่นอน นี่คือตัวอย่างบางส่วน:-
< check if =" {{ @page=='Home' }} " >
< false > < span > Inserted if condition is false </ span > </ false >
</ check >
< check if =" {{ @gender=='M' }} " >
< true >
< div > Appears when condition is true </ div >
</ true >
< false >
< div > Appears when condition is false </ div >
</ false >
</ check >
คุณสามารถมี <check>
สั่งที่ซ้อนกันได้มากเท่าที่คุณต้องการ
นิพจน์ F3 ภายในแอตทริบิวต์ IF ที่เท่ากับ NULL
, สตริงว่างเปล่า, บูลี FALSE
, อาร์เรย์ที่ว่างเปล่าหรือศูนย์, เรียกใช้โดยอัตโนมัติ <false>
หากเทมเพลตของคุณไม่มี <false>
บล็อกแล้วแท็กการเปิดและปิด <true>
เป็นทางเลือก:-
< check if =" {{ @loggedin }} " >
< p > HTML chunk to be included if condition is true </ p >
</ check >
FAT FREE สามารถจัดการบล็อก HTML ซ้ำ ๆ ได้:-
< repeat group =" {{ @fruits }} " value =" {{ @fruit }} " >
< p > {{ trim(@fruit) }} </ p >
</ repeat >
แอตทริบิวต์ group
@fruits
ภายในคำสั่ง <repeat>
ต้องเป็นอาร์เรย์และควรตั้งค่าในรหัส PHP ของคุณตาม:-
$ f3 -> set ( ' fruits ' ,[ ' apple ' , ' orange ' , ' banana ' ]);
ไม่มีอะไรได้รับจากการกำหนดค่าให้ @fruit
ในรหัสแอปพลิเคชันของคุณ FAT-Free ละเว้นค่าที่ตั้งไว้ล่วงหน้าใด ๆ ที่อาจมีเพราะใช้ตัวแปรเพื่อเป็นตัวแทนของรายการปัจจุบันในระหว่างการวนซ้ำมากกว่ากลุ่ม เอาต์พุตของชิ้นส่วนเทมเพลต HTML ด้านบนและรหัส PHP ที่เกี่ยวข้องจะกลายเป็น:-
< p > apple </ p >
< p > orange </ p >
< p > banana </ p >
เฟรมเวิร์กอนุญาตให้มีการทำรังไม่ จำกัด ของ <repeat>
บล็อก:-
< repeat group =" {{ @div }} " key =" {{ @ikey }} " value =" {{ @idiv }} " >
< div >
< p > < span > < b > {{ @ikey }} </ b > </ span > </ p >
< p >
< repeat group =" {{ @idiv }} " value =" {{ @ispan }} " >
< span > {{ @ispan }} </ span >
</ repeat >
</ p >
</ div >
</ repeat >
ใช้คำสั่ง F3 ต่อไปนี้:-
$ f3 -> set ( ' div ' ,
[
' coffee ' =>[ ' arabica ' , ' barako ' , ' liberica ' , ' kopiluwak ' ],
' tea ' =>[ ' darjeeling ' , ' pekoe ' , ' samovar ' ]
]
);
เป็นผลให้คุณได้รับชิ้นส่วน HTML ต่อไปนี้:-
< div >
< p > < span > < b > coffee </ b > </ span > </ p >
< p >
< span > arabica </ span >
< span > barako </ span >
< span > liberica </ span >
< span > kopiluwak </ span >
< p >
</ div >
< div >
< p > < span > < b > tea </ b > </ span > </ p >
< p >
< span > darjeeling </ span >
< span > pekoe </ span >
< span > samovar </ span >
</ p >
</ div >
น่าทึ่งใช่มั้ย และสิ่งเดียวที่คุณต้องทำใน PHP คือการกำหนดเนื้อหาของ div
F3 เดี่ยวเพื่อแทนที่โทเค็น @div
Fat Free ทำให้ทั้งการเขียนโปรแกรมและการออกแบบเทมเพลตเว็บเป็นเรื่องง่ายมาก
แอตทริบิวต์ value
ของเทมเพลต <repeat>
Directive ส่งคืนค่าขององค์ประกอบปัจจุบันในการทำซ้ำ หากคุณต้องการรับคีย์อาร์เรย์ขององค์ประกอบปัจจุบันให้ใช้แอตทริบิวต์ key
แทน แอตทริบิวต์ key
เป็นตัวเลือก
<repeat>
ยังมีแอตทริบิวต์ตัวนับเพิ่มเติมที่สามารถใช้ดังนี้:-
< repeat group =" {{ @fruits }} " value =" {{ @fruit }} " counter =" {{ @ctr }} " >
< p class =" {{ @ctr%2?'odd':'even' }} " > {{ trim(@fruit) }} </ p >
</ repeat >
ภายในเครื่องยนต์เทมเพลตของ F3 จะบันทึกจำนวนการวนซ้ำลูปและบันทึกค่านั้นในตัวแปร/โทเค็น @ctr
ซึ่งใช้ในตัวอย่างของเราเพื่อกำหนดการจำแนกประเภทคี่/แม้กระทั่ง
หากคุณต้องแทรกโทเค็น F3 ภายในส่วน <script>
หรือ <style>
ของเทมเพลตของคุณเฟรมเวิร์กจะยังคงแทนที่ด้วยวิธีปกติ:-
< script type =" text/javascript " >
function notify ( ) {
alert ( 'You are logged in as: {{ @userID }}' ) ;
}
</ script >
การฝังคำสั่งเทมเพลตภายใน <script>
หรือ <style>
แท็กของคุณไม่จำเป็นต้องมีการจัดการพิเศษ:-
< script type =" text/javascript " >
var discounts = [ ] ;
< repeat group = "{{ @rates }}" value = "{{ @rate }}" >
// whatever you want to repeat in Javascript, e.g.
discounts.push(" { { @ rate } } ");
</ repeat >
</ script >
โดยค่าเริ่มต้น Fat Free จะใช้ชุดอักขระ UTF-8 เว้นแต่จะมีการเปลี่ยนแปลง คุณสามารถแทนที่พฤติกรรมนี้ได้โดยการออกบางอย่างเช่น:-
$ f3 -> set ( ' ENCODING ' , ' ISO-8859-1 ' );
เมื่อคุณแจ้งกรอบของชุดอักขระที่ต้องการ F3 จะใช้มันในเทมเพลต HTML และ XML ทั้งหมดจนกว่าจะเปลี่ยนอีกครั้ง
ดังที่ได้กล่าวไว้ก่อนหน้านี้ในส่วนนี้เฟรมเวิร์กไม่ได้ จำกัด อยู่ที่เทมเพลต HTML คุณสามารถประมวลผลเทมเพลต XML ได้เช่นกัน กลไกค่อนข้างคล้ายกันมาก คุณยังคงมี {{ @variable }}
และ {{ expression }}
Tokens, <repeat>
, <check>
, <include>
, และ <exclude>
คำสั่งตามคำสั่งของคุณ เพียงแค่บอก F3 ว่าคุณผ่านไฟล์ XML แทน HTML:-
echo Template:: instance ()-> render ( ' template.xml ' , ' application/xml ' );
อาร์กิวเมนต์ที่สองแสดงถึงประเภท MIME ของเอกสารที่แสดงผล
ส่วนประกอบมุมมองของ MVC ครอบคลุมทุกสิ่งที่ไม่อยู่ภายใต้โมเดลและคอนโทรลเลอร์ซึ่งหมายความว่าการนำเสนอของคุณสามารถและควรรวมส่วนต่อประสานผู้ใช้ทุกชนิดเช่น RSS, อีเมล, RDF, FOAF, ไฟล์ข้อความ ฯลฯ ตัวอย่าง ด้านล่างแสดงวิธีแยกงานนำเสนออีเมลของคุณออกจากตรรกะทางธุรกิจของแอปพลิเคชัน:-
MIME-Version: 1.0
Content-type: text/html; charset={{ @ENCODING }}
From: {{ @from }}
To: {{ @to }}
Subject: {{ @subject }}
< p > Welcome, and thanks for joining {{ @site }}! </ p >
บันทึกเทมเพลตอีเมลด้านบนเป็น welcome.txt รหัส F3 ที่เกี่ยวข้องจะเป็น:-
$ f3 -> set ( ' from ' , ' <[email protected]> ' );
$ f3 -> set ( ' to ' , ' <[email protected]> ' );
$ f3 -> set ( ' subject ' , ' Welcome ' );
ini_set ( ' sendmail_from ' , $ f3 -> get ( ' from ' ));
mail (
$ f3 -> get ( ' to ' ),
$ f3 -> get ( ' subject ' ),
Template:: instance ()-> render ( ' email.txt ' , ' text/html ' )
);
เคล็ดลับ: แทนที่ฟังก์ชั่น SMTP Mail () ด้วย IMAP_MAIL () หากสคริปต์ของคุณสื่อสารกับเซิร์ฟเวอร์ IMAP
ตอนนี้ไม่ใช่อะไร? แน่นอนถ้าคุณมีกลุ่มผู้รับอีเมลคุณจะใช้ฐานข้อมูลเพื่อเติมชื่อ FirstName, LastName และ Tokens อีเมล
นี่คือทางเลือกอื่นโดยใช้ปลั๊กอิน SMTP ของ F3:-
$ mail = new SMTP ( ' smtp.gmail.com ' , 465 , ' SSL ' , ' [email protected] ' , ' secret ' );
$ mail -> set ( ' from ' , ' <[email protected]> ' );
$ mail -> set ( ' to ' , ' "Slasher" <[email protected]> ' );
$ mail -> set ( ' subject ' , ' Welcome ' );
$ mail -> send (Template:: instance ()-> render ( ' email.txt ' ));
F3 รองรับหลายภาษาออกจากกล่อง
ขั้นแรกให้สร้างไฟล์พจนานุกรมที่มีโครงสร้างต่อไปนี้ (หนึ่งไฟล์ต่อภาษา):-
<?php
return [
' love ' => ' I love F3 ' ,
' today ' => ' Today is {0,date} ' ,
' pi ' => ' {0,number} ' ,
' money ' => ' Amount remaining: {0,number,currency} '
];
บันทึกเป็น dict/en.php
มาสร้างพจนานุกรมอื่นกันคราวนี้สำหรับภาษาเยอรมัน บันทึกไฟล์เป็น dict/de.php
:-
<?php
return [
' love ' => ' Ich liebe F3 ' ,
' today ' => ' Heute ist {0,date} ' ,
' money ' => ' Restbetrag: {0,number,currency} '
];
พจนานุกรมไม่มีอะไรมากไปกว่าคู่คีย์-ค่า F3 จะสร้างอินสแตนซ์เฟรมเวิร์กโดยอัตโนมัติตามคีย์ในไฟล์ภาษา ดังนั้นจึงเป็นเรื่องง่ายที่จะฝังตัวแปรเหล่านี้เป็นโทเค็นในเทมเพลตของคุณ ใช้เอ็นจิ้นเทมเพลต F3:-
< h1 > {{ @love }} </ h1 >
< p >
{{ @today,time() | format }}. < br />
{{ @money,365.25 | format }} < br />
{{ @pi }}
</ p >
และรุ่นที่ยาวกว่าที่ใช้ PHP เป็นเอ็นจิ้นเทมเพลต:-
<?php $ f3 =Base:: instance (); ?>
<h1> <?php echo $ f3 -> get ( ' love ' ); ?> </h1>
<p>
<?php echo $ f3 -> get ( ' today ' , time ()); ?> .<br />
<?php echo $ f3 -> get ( ' money ' , 365.25 ); ?>
<?php echo $ f3 -> get ( ' pi ' ); ?>
</p>
ต่อไปเราสั่งให้ F3 มองหาพจนานุกรมใน dict/
folder:-
$ f3 -> set ( ' LOCALES ' , ' dict/ ' );
แต่เฟรมเวิร์กกำหนดว่าจะใช้ภาษาใดได้อย่างไร F3 จะตรวจจับโดยอัตโนมัติโดยดูที่ส่วนหัวคำขอ HTTP ก่อนโดยเฉพาะส่วนหัว Accept-Language
ที่ส่งโดยเบราว์เซอร์
ในการแทนที่พฤติกรรมนี้คุณสามารถทริกเกอร์ F3 ให้ใช้ภาษาที่ระบุโดยผู้ใช้หรือแอปพลิเคชัน:-
$ f3 -> set ( ' LANGUAGE ' , ' de ' );
หมายเหตุ: ในตัวอย่างข้างต้น PI สำคัญมีอยู่เฉพาะในพจนานุกรมภาษาอังกฤษ เฟรมเวิร์กจะใช้ภาษาอังกฤษ ( en
) เป็นทางเลือกเพื่อเติมคีย์ที่ไม่ได้อยู่ในภาษาที่ระบุ (หรือตรวจพบ)
นอกจากนี้คุณยังสามารถสร้างไฟล์พจนานุกรมสำหรับตัวแปรภาษาเช่น en-US
, es-AR
ฯลฯ ในกรณีนี้ F3 จะใช้ตัวแปรภาษาก่อน (เช่น es-AR
) หากมีคีย์ที่ไม่มีอยู่ในตัวแปรเฟรมเวิร์กจะค้นหาคีย์ในภาษารูท ( es
) ให้ใช้ไฟล์ภาษา en
เป็นทางเลือกสุดท้าย พจนานุกรมคีย์-ค่าคู่กลายเป็นตัวแปร F3 เมื่ออ้างอิง ตรวจสอบให้แน่ใจว่าคีย์ไม่ขัดแย้งกับตัวแปรเฟรมเวิร์กใด ๆ อินสแตนซ์ผ่าน $f3->set()
, $f3->mset()
หรือ $f3->config()
คุณสังเกตเห็นรูปแบบที่แปลกประหลาด 'Today is {0,date}'
ในตัวอย่างก่อนหน้าของเราหรือไม่? บานพับความสามารถหลายภาษาของ F3 บนกฎการจัดรูปแบบสตริง/ข้อความของโครงการ ICU เฟรมเวิร์กใช้ชุดย่อยของตัวเองของการใช้งานการจัดรูปแบบสตริง ICU ไม่จำเป็นต้องเปิดใช้งานส่วนขยาย intl
ของ PHP บนเซิร์ฟเวอร์
อีกอย่างหนึ่ง: F3 ยังสามารถโหลดไฟล์ที่จัดรูปแบบ.
love = " I love F3 "
today = " Today is {0,date} "
pi = " {0,number} "
money = " Amount remaining: {0,number,currency} "
บันทึกเป็น dict/en.ini
เพื่อให้เฟรมเวิร์กสามารถโหลดได้โดยอัตโนมัติ
โดยค่าเริ่มต้นทั้ง View Handler และ Template Engine จะหลบหนีตัวแปรที่แสดงผลทั้งหมดเช่นแปลงเป็นเอนทิตี HTML เพื่อปกป้องคุณจาก XSS ที่เป็นไปได้และการโจมตีการฉีดรหัส ในทางกลับกันหากคุณต้องการส่งชิ้นส่วน HTML ที่ถูกต้องจากรหัสแอปพลิเคชันไปยังเทมเพลตของคุณ:-
$ f3 -> set ( ' ESCAPE ' , FALSE );
สิ่งนี้อาจมีผลที่ไม่พึงประสงค์ คุณอาจไม่ต้องการให้ตัวแปรทั้งหมดผ่าน Unsespaped ปลอดไขมันช่วยให้คุณสามารถแยกแยะตัวแปรแยกกันได้ สำหรับเทมเพลต F3:-
{{ @html_content | raw }}
ในกรณีของเทมเพลต PHP:-
<?php echo View:: instance ()-> raw ( $ html_content ); ?>
นอกเหนือจากการหายใจอัตโนมัติของตัวแปร F3 เฟรมเวิร์กยังช่วยให้คุณได้ฟรีในการป้อนข้อมูลผู้ใช้ในการฆ่าเชื้อจากรูปแบบ HTML:-
$ f3 -> scrub ( $ _GET , ' p; br; span; div; a ' );
คำสั่งนี้จะแยกแท็กทั้งหมด (ยกเว้นที่ระบุในอาร์กิวเมนต์ที่สอง) และอักขระที่ไม่ปลอดภัยจากตัวแปรที่ระบุ หากตัวแปรมีอาร์เรย์แต่ละองค์ประกอบในอาร์เรย์จะถูกทำให้เป็นมนุษย์ซ้ำซาก หาก Asterisk (*) ถูกส่งผ่านเป็นอาร์กิวเมนต์ที่สอง $f3->scrub()
อนุญาตให้แท็ก HTML ทั้งหมดผ่านการไม่ถูกแตะต้องและเพียงลบอักขระควบคุมที่ไม่ปลอดภัย
Fat Free ได้รับการออกแบบมาเพื่อให้งานเชื่อมต่อกับฐานข้อมูล SQL เป็นเรื่องง่าย หากคุณไม่ได้เป็นประเภทที่จะดื่มด่ำกับรายละเอียดเกี่ยวกับ SQL แต่พึ่งพาการจัดการข้อมูลเชิงวัตถุมากขึ้นคุณสามารถไปยังส่วนถัดไปของบทช่วยสอนนี้ได้โดยตรง อย่างไรก็ตามหากคุณต้องการทำงานการจัดการข้อมูลที่ซับซ้อนและการเพิ่มประสิทธิภาพของฐานข้อมูล SQL เป็นวิธีที่จะไป
การสร้างการสื่อสารด้วยเอ็นจิ้น SQL เช่น MySQL, SQLITE, SQL Server, Sybase และ Oracle ทำได้โดยใช้คำสั่ง $f3->set()
ที่คุ้นเคย การเชื่อมต่อกับฐานข้อมูล sqlite จะเป็น:-
$ db = new DB SQL ( ' sqlite:/absolute/path/to/your/database.sqlite ' );
อีกตัวอย่างหนึ่งครั้งนี้กับ MySQL:-
$ db = new DB SQL (
' mysql:host=localhost;port=3306;dbname=mysqldb ' ,
' admin ' ,
' p455w0rD '
);
ตกลง. มันง่ายใช่มั้ย นั่นเป็นวิธีที่คุณจะทำสิ่งเดียวกันใน PHP ธรรมดา คุณเพียงแค่ต้องรู้รูปแบบ DSN ของฐานข้อมูลที่คุณกำลังเชื่อมต่อ ดูส่วน PDO ของคู่มือ PHP
ลองดำเนินการต่อรหัส PHP ของเรา:-
$ f3 -> set ( ' result ' , $ db -> exec ( ' SELECT brandName FROM wherever ' ));
echo Template:: instance ()-> render ( ' abc.htm ' );
ฮะเกิดอะไรขึ้นที่นี่? เราไม่ควรตั้งค่าสิ่งต่าง ๆ เช่น PDOs ข้อความเคอร์เซอร์ ฯลฯ หรือไม่? คำตอบง่ายๆคือคุณไม่จำเป็นต้องทำ F3 ทำให้ทุกอย่างง่ายขึ้นโดยการดูแลการทำงานหนักทั้งหมดในแบ็กเอนด์
เวลานี้เราสร้างเทมเพลต HTML เช่น abc.htm
ที่มีขั้นต่ำต่อไปนี้:-
< repeat group =" {{ @result }} " value =" {{ @item }} " >
< span > {{ @item.brandName }} </ span >
</ repeat >
ในกรณีส่วนใหญ่ชุดคำสั่ง SQL ควรเพียงพอที่จะสร้างผลลัพธ์ที่พร้อมใช้งานเว็บเพื่อให้คุณสามารถใช้ตัวแปรอาเรย์ result
ในเทมเพลตของคุณโดยตรง เป็นไปได้อย่างที่มันอาจจะปราศจากไขมันจะไม่หยุดคุณจากการเข้าสู่ SQL Handler Internals ในความเป็นจริงคลาส DBSQL
ของ F3 นั้นมาจากคลาส PDO
ของ PDP โดยตรงดังนั้นคุณยังสามารถเข้าถึงส่วนประกอบ PDO และดั้งเดิมที่เกี่ยวข้องในแต่ละกระบวนการหากคุณต้องการการควบคุมแบบละเอียด
นี่เป็นอีกตัวอย่างหนึ่ง แทนที่จะเป็นคำสั่งเดียวที่ให้ไว้เป็นอาร์กิวเมนต์ของคำสั่ง $db->exec()
คุณยังสามารถส่งอาร์เรย์ของคำสั่ง SQL:-
$ db -> exec (
[
' DELETE FROM diet WHERE food="cola" ' ,
' INSERT INTO diet (food) VALUES ("carrot") ' ,
' SELECT * FROM diet '
]
);
F3 นั้นฉลาดพอที่จะรู้ว่าหากคุณผ่านคำแนะนำ SQL อาร์เรย์สิ่งนี้บ่งชี้ว่าการทำธุรกรรมชุด SQL คุณไม่ต้องกังวลเกี่ยวกับการย้อนกลับ SQL และการดำเนินการเนื่องจากเฟรมเวิร์กจะเปลี่ยนกลับไปเป็นสถานะเริ่มต้นของฐานข้อมูลโดยอัตโนมัติหากเกิดข้อผิดพลาดใด ๆ ในระหว่างการทำธุรกรรม หากประสบความสำเร็จ F3 จะทำการเปลี่ยนแปลงทั้งหมดที่เกิดขึ้นกับฐานข้อมูล
นอกจากนี้คุณยังสามารถเริ่มต้นและสิ้นสุดการทำธุรกรรมทางโปรแกรม:-
$ db -> begin ();
$ db -> exec ( ' DELETE FROM diet WHERE food="cola" ' );
$ db -> exec ( ' INSERT INTO diet (food) VALUES ("carrot") ' );
$ db -> exec ( ' SELECT * FROM diet ' );
$ db -> commit ();
การย้อนกลับจะเกิดขึ้นหากข้อความใด ๆ พบข้อผิดพลาด
เพื่อรับรายการคำแนะนำฐานข้อมูลทั้งหมดที่ออก:-
echo $ db -> log ();
การผ่านข้อโต้แย้งสตริงไปยังคำสั่ง SQL นั้นเต็มไปด้วยอันตราย พิจารณาสิ่งนี้:-
$ db -> exec (
' SELECT * FROM users ' .
' WHERE username=" ' . $ f3 -> get ( ' POST.userID ' . ' " ' )
);
หาก userID
POST
ตัวแปรไม่ผ่านกระบวนการสุขาภิบาลข้อมูลผู้ใช้ที่เป็นอันตรายสามารถผ่านสตริงต่อไปนี้และทำลายฐานข้อมูลของคุณกลับไม่ได้:-
admin " ; DELETE FROM users; SELECT " 1
โชคดีที่การสืบค้นพารามิเตอร์ช่วยคุณลดความเสี่ยงเหล่านี้:-
$ db -> exec (
' SELECT * FROM users WHERE userID=? ' ,
$ f3 -> get ( ' POST.userID ' )
);
หาก F3 ตรวจพบว่าค่าของพารามิเตอร์/โทเค็นแบบสอบถามเป็นสตริงเลเยอร์การเข้าถึงข้อมูลพื้นฐานจะหนีสตริงและเพิ่มราคาตามความจำเป็น
ตัวอย่างของเราในส่วนก่อนหน้านี้จะปลอดภัยกว่ามากจากการฉีด SQL หากเขียนด้วยวิธีนี้:-
$ db -> exec (
[
' DELETE FROM diet WHERE food=:name ' ,
' INSERT INTO diet (food) VALUES (?) ' ,
' SELECT * FROM diet '
],
[
array ( ' :name ' => ' cola ' ),
array ( 1 => ' carrot ' ),
NULL
]
);
F3 เต็มไปด้วยแผนที่ความสัมพันธ์เชิงวัตถุที่ใช้งานง่าย (ORM) ที่อยู่ระหว่างแอปพลิเคชันของคุณและข้อมูลของคุณ-ทำให้ง่ายขึ้นและเร็วขึ้นสำหรับคุณในการเขียนโปรแกรมที่จัดการการทำงานของข้อมูลทั่วไปเช่นการสร้างการดึงการอัปเดต และการลบข้อมูล (CRUD) จากฐานข้อมูล SQL และ NOSQL ตัวแม็พข้อมูลทำงานส่วนใหญ่โดยการแมปการโต้ตอบของวัตถุ PHP กับแบบสอบถามแบ็กเอนด์ที่สอดคล้องกัน
สมมติว่าคุณมีฐานข้อมูล MySQL ที่มีอยู่ซึ่งมีตารางผู้ใช้แอปพลิเคชันของคุณ (SQLite, PostgreSQL, SQL Server, Sybase จะทำเช่นกัน) มันจะถูกสร้างขึ้นโดยใช้คำสั่ง SQL ต่อไปนี้:-
CREATE TABLE users (
userID VARCHAR ( 30 ),
password VARCHAR ( 30 ),
visits INT ,
PRIMARY KEY (userID)
);
หมายเหตุ: MongoDB เป็นเอ็นจินฐานข้อมูล NOSQL และสคีมาโดยเนื้อแท้ F3 มีการใช้งาน NOSQL ที่รวดเร็วและมีน้ำหนักเบาที่เรียกว่า JIG ซึ่งใช้ไฟล์แฟลต PHP-serialized หรือ JSON ที่เข้ารหัส เลเยอร์ที่เป็นนามธรรมเหล่านี้ไม่จำเป็นต้องมีโครงสร้างข้อมูลที่เข้มงวด ฟิลด์อาจแตกต่างกันไปจากบันทึกหนึ่งไปยังอีกบันทึกหนึ่ง พวกเขายังสามารถกำหนดหรือลดลงได้ทันที
ตอนนี้กลับไปที่ SQL ก่อนอื่นเราสร้างการสื่อสารกับฐานข้อมูลของเรา
$ db = new DB SQL (
' mysql:host=localhost;port=3306;dbname=mysqldb ' ,
' admin ' ,
' wh4t3v3r '
);
เพื่อดึงบันทึกจากตารางของเรา:-
$ user = new DB SQL Mapper ( $ db , ' users ' );
$ user -> load ([ ' userID=? ' , ' tarzan ' ]);
บรรทัดแรกทำให้วัตถุ Mapper Data Mapper สร้างโต้ตอบกับตาราง users
ในฐานข้อมูลของเรา เบื้องหลังฉาก F3 ดึงโครงสร้างของตาราง users
และกำหนดว่าฟิลด์ใดที่ถูกกำหนดเป็นคีย์หลัก ณ จุดนี้วัตถุ Mapper ยังไม่มีข้อมูล (สถานะแห้ง) ดังนั้น $user
จะไม่มีอะไรมากไปกว่าวัตถุที่มีโครงสร้าง - แต่มีวิธีการที่จำเป็นในการดำเนินการ CRUD พื้นฐานและความพิเศษบางอย่าง ในการดึงบันทึกจากตารางผู้ใช้ของเราด้วยฟิลด์ userID
ที่มีค่าสตริง tarzan
เราใช้ load() method
กระบวนการนี้เรียกว่า "การเพิ่มความชุ่มชื้นอัตโนมัติ" วัตถุ Data Mapper
ง่ายใช่มั้ย? F3 เข้าใจว่าตาราง SQL มีคำจำกัดความโครงสร้างที่มีอยู่แล้วภายในเอ็นจินฐานข้อมูลเอง ซึ่งแตกต่างจากเฟรมเวิร์กอื่น ๆ F3 ไม่จำเป็นต้องมีการประกาศในชั้นเรียนพิเศษ (เว้นแต่คุณต้องการขยายตัวแม็พข้อมูลให้พอดีกับวัตถุที่ซับซ้อน) ไม่มีการแมปคุณสมบัติ PHP/อาร์กไขึ้นไปทำแผนที่วัตถุไปสู่ฟิลด์ (การทำซ้ำของความพยายาม) การฟื้นฟูหากโครงสร้างฐานข้อมูลเปลี่ยนไป) ไม่มีไฟล์ XML/YAML โง่ ๆ เพื่อกำหนดค่าโมเดลของคุณไม่มีคำสั่งที่ฟุ่มเฟือยเพียงเพื่อดึงบันทึกเดียว ด้วย F3 การปรับขนาดฟิลด์ varchar
อย่างง่ายใน MySQL ไม่ต้องการการเปลี่ยนแปลงในรหัสแอปพลิเคชันของคุณ สอดคล้องกับ MVC และ "การแยกข้อกังวล" ผู้ดูแลระบบฐานข้อมูลมีการควบคุมข้อมูล (และโครงสร้าง) มากเท่าที่นักออกแบบแม่แบบมีเทมเพลต HTML/XML
หากคุณต้องการทำงานกับฐานข้อมูล NOSQL ความคล้ายคลึงกันในไวยากรณ์การสืบค้นนั้นเป็นเพียงผิวเผิน ในกรณีของ MongoDB Data Mapper รหัสเทียบเท่าจะเป็น:-
$ db = new DB Mongo ( ' mongodb://localhost:27017 ' , ' testdb ' );
$ user = new DB Mongo Mapper ( $ db , ' users ' );
$ user -> load ([ ' userID ' => ' tarzan ' ]);
ด้วยจิ๊กไวยากรณ์จะคล้ายกับเอ็นจิ้นเทมเพลตของ F3:-
$ db = new DB Jig ( ' db/data/ ' , DB Jig:: FORMAT_JSON );
$ user = new DB Jig Mapper ( $ db , ' users ' );
$ user -> load ([ ' @userID=? ' , ' tarzan ' ]);
เฟรมเวิร์กแมป visits
ฟิลด์ในตารางของเราโดยอัตโนมัติไปยังคุณสมบัติการแม็กข้อมูลในระหว่างการสร้างอินสแตนซ์ของวัตถุเช่น $user=new DBSQLMapper($db,'users');
- เมื่อวัตถุถูกสร้างขึ้นแล้ว $user->password
และ $user->userID
จะแมปกับ password
และฟิลด์ userID
ในตารางของเราตามลำดับ
คุณไม่สามารถเพิ่มหรือลบฟิลด์ที่แมปหรือเปลี่ยนโครงสร้างของตารางโดยใช้ ORM คุณต้องทำสิ่งนี้ใน MySQL หรือเอ็นจินฐานข้อมูลใด ๆ ที่คุณใช้ หลังจากที่คุณทำการเปลี่ยนแปลงในเอ็นจิ้นฐานข้อมูลของคุณ FAT-Free จะซิงโครไนซ์โครงสร้างตารางใหม่โดยอัตโนมัติกับวัตถุ Data Mapper ของคุณเมื่อคุณเรียกใช้แอปพลิเคชัน
F3 ได้มาจากโครงสร้างข้อมูล Mapper โดยตรงจากสคีมาฐานข้อมูล ไม่มีการคาดเดาที่เกี่ยวข้อง เข้าใจถึงความแตกต่างระหว่าง MySQL, SQLITE, MSSQL, SYBASE และ Engines ฐานข้อมูล PostgreSQL
ตัวระบุ SQL ไม่ควรใช้คำที่สงวนไว้และควร จำกัด เฉพาะอักขระตัวอักษรและตัวเลข AZ
, 0-9
และสัญลักษณ์ขีดเส้นใต้ ( _
) ชื่อคอลัมน์ที่มีช่องว่าง (หรืออักขระพิเศษ) และล้อมรอบด้วยเครื่องหมายคำพูดในนิยามข้อมูลไม่สามารถใช้งานได้กับ ORM ไม่สามารถแสดงได้อย่างถูกต้องเป็นคุณสมบัติของวัตถุ PHP
สมมติว่าเราต้องการเพิ่มจำนวนการเข้าชมของผู้ใช้และอัปเดตระเบียนที่เกี่ยวข้องในตารางผู้ใช้ของเราเราสามารถเพิ่มรหัสต่อไปนี้:-
$ user -> visits ++;
$ user -> save ();
หากเราต้องการแทรกบันทึกเราทำตามกระบวนการนี้:-
$ user = new DB SQL Mapper ( $ db , ' users ' );
// or $ user = new DB Mongo Mapper ($ db , 'users' );
// or $ user = new DB Jig Mapper ($ db , 'users' );
$ user -> userID = ' jane ' ;
$ user -> password = password_hash ( ' secret ' , PASSWORD_BCRYPT , [ ' cost ' => 12 ]);
$ user -> visits = 0 ;
$ user -> save ();
เรายังคงใช้วิธี save()
แต่ F3 จะรู้ได้อย่างไรว่าควรแทรกหรืออัปเดตเร็กคอร์ดเมื่อใด ในขณะที่วัตถุข้อมูล Mapper ได้รับการชุ่มชื้นโดยอัตโนมัติโดยการดึงบันทึกเฟรมเวิร์กจะติดตามคีย์หลักของบันทึก (หรือ _id
ในกรณีของ MongoDB และ JIG) - ดังนั้นจึงรู้ว่าควรอัปเดตหรือลบบันทึกใด - แม้กระทั่ง เมื่อค่าของคีย์หลักมีการเปลี่ยนแปลง การแม็กข้อมูลที่มีความชุ่มชื้นแบบโปรแกรม - ค่าที่ไม่ได้ดึงมาจากฐานข้อมูล แต่เติมโดยแอปพลิเคชัน - จะไม่มีหน่วยความจำใด ๆ ของค่าก่อนหน้าในคีย์หลัก เช่นเดียวกับ MongoDB และ JIG แต่ใช้วัตถุ _id
เป็นข้อมูลอ้างอิง ดังนั้นเมื่อเราสร้างอินสแตนซ์วัตถุ $user
ด้านบนและเติมคุณสมบัติของมันด้วยค่าจากโปรแกรมของเรา - โดยไม่ต้องดึงบันทึกจากตารางผู้ใช้ F3 รู้ว่าควรแทรกบันทึกนี้
วัตถุ Mapper จะไม่ว่างหลังจาก save()
หากคุณต้องการเพิ่มระเบียนใหม่ลงในฐานข้อมูลของคุณคุณต้องคายน้ำมาก่อน:-
$ user -> reset ();
$ user -> userID = ' cheetah ' ;
$ user -> password = password_hash ( ' unknown ' , PASSWORD_BCRYPT , [ ' cost ' => 12 ]);
$ user -> save ();
การโทร save()
ครั้งที่สองโดยไม่เรียกใช้ reset()
จะอัปเดตบันทึกที่ชี้ไปที่ผู้ทำแผนที่ในปัจจุบัน
แม้ว่าปัญหาของการมีคีย์หลักในทุกตารางในฐานข้อมูลของคุณคือการโต้แย้ง แต่ F3 ไม่ได้หยุดคุณจากการสร้างวัตถุ Data Mapper ที่สื่อสารกับตารางที่ไม่มีปุ่มหลัก ข้อเสียเปรียบเพียงอย่างเดียวคือ: คุณไม่สามารถลบหรืออัปเดตเร็กคอร์ดที่แมปได้เนื่องจากไม่มีวิธีใดที่ F3 ในการพิจารณาว่าคุณอ้างถึงบันทึกใดที่คุณอ้างถึงบวกกับความจริงที่ว่าการอ้างอิงตำแหน่งไม่น่าเชื่อถือ ID แถวไม่สามารถพกพาได้ในเครื่องยนต์ SQL ที่แตกต่างกันและอาจไม่ถูกส่งคืนโดยไดรเวอร์ฐานข้อมูล PHP
ในการลบบันทึกที่แมปออกจากตารางของเราให้เรียกใช้วิธี erase()
บนแผนที่ข้อมูลอัตโนมัติ ตัวอย่างเช่น:-
$ user = new DB SQL Mapper ( $ db , ' users ' );
$ user -> load ([ ' userID=? AND password=? ' , ' cheetah ' , ' ch1mp ' ]);
$ user -> erase ();
ไวยากรณ์การสืบค้นของจิ๊กจะคล้ายกันเล็กน้อย:-
$ user = new DB Jig Mapper ( $ db , ' users ' );
$ user -> load ([ ' @userID=? AND @password=? ' , ' cheetah ' , ' chimp ' ]);
$ user -> erase ();
และ MongoDB เทียบเท่าจะเป็น:-
$ user = new DB Mongo Mapper ( $ db , ' users ' );
$ user -> load ([ ' userID ' => ' cheetah ' , ' password ' => ' chimp ' ]);
$ user -> erase ();
เพื่อค้นหาว่า Mapper ข้อมูลของเรานั้นชุ่มชื้นหรือไม่:-
if ( $ user -> dry ())
echo ' No record matching criteria ' ;
เราได้ครอบคลุมตัวจัดการ CRUD มีวิธีพิเศษบางอย่างที่คุณอาจพบว่ามีประโยชน์:-
$ f3 -> set ( ' user ' , new DB SQL Mapper ( $ db , ' users ' ));
$ f3 -> get ( ' user ' )-> copyFrom ( ' POST ' );
$ f3 -> get ( ' user ' )-> save ();
ขอให้สังเกตว่าเรายังสามารถใช้ตัวแปรปลอดไขมันเป็นภาชนะสำหรับวัตถุ Mapper เมธอด copyFrom()
ให้ความชุ่มชื้นกับวัตถุ Mapper ด้วยองค์ประกอบจากตัวแปร Array Framework คีย์อาร์เรย์ซึ่งต้องมีชื่อที่เหมือนกันกับคุณสมบัติของวัตถุ Mapper ซึ่งจะสอดคล้องกับชื่อฟิลด์ของบันทึก ดังนั้นเมื่อมีการส่งแบบฟอร์มเว็บ (สมมติว่าแอตทริบิวต์ชื่อ HTML ถูกตั้งค่าเป็น userID
) เนื้อหาของฟิลด์อินพุตนั้นจะถูกถ่ายโอนไปยัง $_POST['userID']
ซึ่งทำซ้ำโดย F3 ในตัวแปร POST.userID
ฟิลด์ที่แม็พ $user->userID
ในฐานข้อมูล กระบวนการนี้ง่ายมากหากพวกเขามีองค์ประกอบที่มีชื่อเหมือนกัน ความสอดคล้องในคีย์อาร์เรย์เช่นชื่อโทเค็นเทมเพลตชื่อตัวแปรเฟรมเวิร์กชื่อและชื่อฟิลด์คือคีย์ :)
ในทางกลับกันหากเราต้องการดึงบันทึกและคัดลอกค่าฟิลด์ไปยังตัวแปรเฟรมเวิร์กสำหรับการใช้งานในภายหลังเช่นการแสดงผลแม่แบบ:-
$ f3 -> set ( ' user ' , new DB SQL Mapper ( $ db , ' users ' ));
$ f3 -> get ( ' user ' )-> load ([ ' userID=? ' , ' jane ' ]);
$ f3 -> get ( ' user ' )-> copyTo ( ' POST ' );
จากนั้นเราสามารถกำหนด {{ @post.userid}} ให้กับแอตทริบิวต์ค่าของฟิลด์อินพุตเดียวกัน เพื่อสรุปฟิลด์อินพุต HTML จะมีลักษณะเช่นนี้:-
< input type =" text " name =" userID " value =" {{ @POST.userID }} " />
วิธีการบันทึก save()
, update()
, copyFrom()
data mapper และตัวแปรพารามิเตอร์ของ load()
และ erase()
ปลอดภัยจากการฉีด SQL
โดยค่าเริ่มต้นวิธี load()
จะดึงเฉพาะระเบียนแรกที่ตรงกับเกณฑ์ที่ระบุ หากคุณมีมากกว่าหนึ่งที่ตรงตามเงื่อนไขเดียวกันกับบันทึกแรกที่โหลดคุณสามารถใช้วิธี skip()
สำหรับการนำทาง:-
$ user = new DB SQL Mapper ( $ db , ' users ' );
$ user -> load ( ' visits>3 ' );
// Rewritten as a parameterized query
$ user -> load ([ ' visits>? ' , 3 ]);
// For MongoDB users : -
// $ user = new DB Mongo Mapper ($ db , 'users' );
// $ user - > load ([ 'visits' = > [ '$gt' = > 3 ]]);
// If you prefer Jig : -
// $ user = new DB Jig Mapper ($ db , 'users' );
// $ user - > load ( '@visits>?' , 3 );
// Display the userID of the first record that matches the criteria
echo $ user -> userID ;
// Go to the next record that matches the same criteria
$ user -> skip (); // Same as $ user - > skip ( 1 );
// Back to the first record
$ user -> skip (- 1 );
// Move three records forward
$ user -> skip ( 3 );
คุณสามารถใช้ $user->next()
แทนสำหรับ $user->skip()
และ $user->prev()
หากคุณคิดว่ามันให้ความหมายมากขึ้นกับ $user->skip(-1)
ใช้วิธี dry()
เพื่อตรวจสอบว่าคุณมีการจัดทำเกินขีด จำกัด ของชุดผลลัพธ์หรือไม่ dry()
จะกลับมาเป็นจริงถ้าคุณลอง skip(-1)
ในบันทึกแรก มันจะกลับมาเป็นจริงถ้าคุณ skip(1)
ในบันทึกสุดท้ายที่ตรงตามเกณฑ์การดึงข้อมูล
วิธี load()
ยอมรับอาร์กิวเมนต์ที่สอง: อาร์เรย์ของตัวเลือกที่มีคู่คีย์-ค่าเช่น:-
$ user -> load (
[ ' visits>? ' , 3 ],
[
' order ' => ' userID DESC '
'offset'=> 5 ,
' limit ' => 3
]
);
หากคุณใช้ mysql แบบสอบถามแปลเป็น:-
SELECT * FROM users
WHERE visits > 3
ORDER BY userID DESC
LIMIT 3 OFFSET 5 ;
นี่เป็นวิธีหนึ่งในการนำเสนอข้อมูลในชิ้นเล็ก ๆ นี่เป็นอีกวิธีหนึ่งในการแสดงผลผลลัพธ์:-
$ page = $ user -> paginate ( 2 , 5 ,[ ' visits>? ' , 3 ]);
ในสถานการณ์ข้างต้น F3 จะดึงระเบียนที่ตรงกับเกณฑ์ 'visits>3'
จากนั้นจะ จำกัด ผลลัพธ์ไว้ที่ 5 ระเบียน (ต่อหน้า) เริ่มต้นที่หน้าชดเชย 2 (ตาม 0) เฟรมเวิร์กจะส่งคืนอาร์เรย์ซึ่งประกอบด้วยองค์ประกอบต่อไปนี้:-
[subset] array of mapper objects that match the criteria
[count] number of subsets available
[pos] actual subset position
ตำแหน่งส่วนย่อยที่ส่งคืนจริงจะเป็นโมฆะหากอาร์กิวเมนต์แรกของ paginate()
เป็นจำนวนลบหรือเกินจำนวนชุดย่อยที่พบ
มีกรณีที่คุณต้องการดึงค่าที่คำนวณได้ของฟิลด์หรือค่าอ้างอิงข้ามจากตารางอื่น ป้อนฟิลด์เสมือนจริง SQL mini-orm ช่วยให้คุณสามารถทำงานกับข้อมูลที่ได้จากเขตข้อมูลที่มีอยู่
สมมติว่าเรามีตารางต่อไปนี้ที่กำหนดเป็น:-
CREATE TABLE products
productID VARCHAR ( 30 ),
description VARCHAR ( 255 ),
supplierID VARCHAR ( 30 ),
unitprice DECIMAL ( 10 , 2 ),
quantity INT ,
PRIMARY KEY (productID)
);
ไม่มีฟิลด์ totalprice
ดังนั้นเราจึงสามารถบอกเฟรมเวิร์กให้ร้องขอจากเอ็นจิ้นฐานข้อมูลผลิตภัณฑ์เลขคณิตของทั้งสองฟิลด์:-
$ item = new DB SQL Mapper ( $ db , ' products ' );
$ item -> totalprice = ' unitprice*quantity ' ;
$ item -> load ([ ' productID=:pid ' , ' :pid ' => ' apple ' ]);
echo $ item -> totalprice ;
ตัวอย่างโค้ดด้านบนกำหนดฟิลด์เสมือนที่เรียกว่า totalprice
ซึ่งคำนวณโดยการคูณ unitprice
ด้วย quantity
SQL Mapper บันทึกกฎ/สูตรนั้นดังนั้นเมื่อถึงเวลาที่จะดึงบันทึกจากฐานข้อมูลเราสามารถใช้ฟิลด์เสมือนจริงเช่นฟิลด์แมปปกติ
คุณสามารถมีฟิลด์เสมือนที่ซับซ้อนมากขึ้น:-
$ item -> mostNumber = ' MAX(quantity) ' ;
$ item -> load ();
echo $ item -> mostNumber ;
เวลานี้เฟรมเวิร์กดึงผลิตภัณฑ์ด้วยปริมาณสูงสุด (สังเกตวิธี load()
ไม่ได้กำหนดเกณฑ์ใด ๆ ดังนั้นบันทึกทั้งหมดในตารางจะถูกประมวลผล) แน่นอนฟิลด์เสมือนจริง mostNumber
จะยังคงให้ตัวเลขที่ถูกต้องหากคุณต้องการ จำกัด นิพจน์ให้กับกลุ่มบันทึกเฉพาะที่ตรงกับเกณฑ์ที่ระบุ
นอกจากนี้คุณยังสามารถได้รับค่าจากตารางอื่น:-
$ item -> supplierName =
' SELECT name FROM suppliers ' .
' WHERE products.supplierID=suppliers.supplierID ' ;
$ item -> load ();
echo $ item -> supplierName ;
ทุกครั้งที่คุณโหลดบันทึกจากตารางผลิตภัณฑ์ ORM การอ้างอิงข้าม ORM supplerID
ในตาราง products
กับ supplierID
ในตาราง suppliers
หากต้องการทำลายฟิลด์เสมือนให้ใช้ unset($item->totalPrice);
- นิพจน์ isset($item->totalPrice)
จะส่งคืนจริงหากฟิลด์เสมือน totalPrice
Virtual ถูกกำหนดหรือเท็จถ้าเป็นอย่างอื่น
โปรดจำไว้ว่าต้องมีการกำหนดฟิลด์เสมือนจริงก่อนการดึงข้อมูล ORM ไม่ได้ทำการคำนวณจริงหรือการได้รับผลลัพธ์จากตารางอื่น มันเป็นเอ็นจินฐานข้อมูลที่ทำงานหนักทั้งหมด
หากคุณไม่จำเป็นต้องมีการนำทางบันทึกโดยบันทึกคุณสามารถดึงบันทึกชุดทั้งหมดในนัดเดียว:-
$ frequentUsers = $ user -> find ([ ' visits>? ' , 3 ],[ ' order ' => ' userID ' ]);
ไวยากรณ์การสืบค้นของ Jig Mapper มีความคล้ายคลึงกันเล็กน้อย:-
$ frequentUsers = $ user -> find ([ ' @visits>? ' , 3 ],[ ' order ' => ' userID ' ]);
รหัสเทียบเท่าโดยใช้ MongoDB Mapper:-
$ frequentUsers = $ user -> find ([ ' visits ' =>[ ' $gt ' => 3 ]],[ ' userID ' => 1 ]);
วิธี find()
ค้นหาตาราง users
สำหรับระเบียนที่ตรงกับเกณฑ์เรียงลำดับผลลัพธ์ด้วย userID
และส่งคืนผลลัพธ์เป็นอาร์เรย์ของวัตถุ MAPPER find('visits>3')
แตกต่างจาก load('visits>3')
หลังหมายถึงวัตถุ $user
ปัจจุบัน find()
ไม่มีผลกระทบใด ๆ ต่อ skip()
สำคัญ: การประกาศสภาพที่ว่างเปล่า null หรือสตริงความยาวเป็นศูนย์เป็นอาร์กิวเมนต์แรกของ find()
หรือ load()
จะเรียกคืนระเบียนทั้งหมด ให้แน่ใจว่าคุณรู้ว่าคุณกำลังทำอะไร - คุณอาจเกิน Memory_limit ของ PHP บนโต๊ะหรือคอลเลกชันขนาดใหญ่
วิธี find()
มีไวยากรณ์ต่อไปนี้:-
find (
$ criteria ,
[
' group ' => ' foo ' ,
' order ' => ' foo,bar ' ,
' limit ' => 5 ,
' offset ' => 0
]
);
ค้นหา () ส่งคืนอาร์เรย์ของวัตถุ แต่ละวัตถุเป็น mapper ไปยังระเบียนที่ตรงกับเกณฑ์ที่ระบุ :-
$ place = new DB SQL Mapper ( $ db , ' places ' );
$ list = $ place -> find ( ' state="New York" ' );
foreach ( $ list as $ obj )
echo $ obj -> city . ' , ' . $ obj -> country ;
หากคุณต้องการแปลงวัตถุแผนที่เป็นอาร์เรย์เชื่อมโยงให้ใช้วิธี cast()
:-
$ array = $ place -> cast ();
echo $ array [ ' city ' ]. ' , ' . $ array [ ' country ' ];
ในการดึงจำนวนระเบียนในตารางที่ตรงกับเงื่อนไขที่แน่นอนให้ใช้วิธี count()
if (! $ user -> count ([ ' visits>? ' , 10 ]))
echo ' We need a better ad campaign! ' ;
นอกจากนี้ยังมีวิธี select()
ที่คล้ายกับ find()
แต่ให้การควบคุมที่ดีกว่าฟิลด์ที่ส่งคืน มันมีไวยากรณ์เหมือน SQL:-
select (
' foo, bar, MIN(baz) AS lowest ' ,
' foo > ? ' ,
[
' group ' => ' foo, bar ' ,
' order ' => ' baz ASC ' ,
' limit ' => 5 ,
' offset ' => 3
]
);
เช่นเดียวกับวิธี find()
select()
ไม่ได้เปลี่ยนเนื้อหาของวัตถุ Mapper มันทำหน้าที่เป็นวิธีการสะดวกสำหรับการสืบค้นตารางที่แมป ค่าส่งคืนของทั้งสองวิธีคืออาร์เรย์ของวัตถุ MAPPER การใช้ dry()
เพื่อตรวจสอบว่ามีการบันทึกโดยวิธีการเหล่านี้ไม่เหมาะสมหรือไม่ หากไม่มีการบันทึกตรงกับเกณฑ์ find()
หรือ select()
ค่าส่งคืนเป็นอาร์เรย์ที่ว่างเปล่า
หากคุณต้องการทราบว่าคำสั่ง SQL ที่ออกโดยแอปพลิเคชันของคุณโดยตรง (หรือผ่านวัตถุ Mapper ทางอ้อม) กำลังก่อให้เกิดปัญหาคอขวดคุณสามารถทำได้อย่างง่าย ๆ :-
echo $ db -> log ();
F3 ติดตามคำสั่งทั้งหมดที่ออกให้กับไดรเวอร์ฐานข้อมูล SQL พื้นฐานรวมถึงเวลาที่แต่ละคำสั่งจะเสร็จสมบูรณ์ - เพียงข้อมูลที่เหมาะสมที่คุณต้องปรับแต่งประสิทธิภาพของแอปพลิเคชัน
ในกรณีส่วนใหญ่คุณสามารถใช้ชีวิตได้โดยความสะดวกสบายที่ได้รับจากวิธีการทำแผนที่ข้อมูลที่เราได้กล่าวถึงจนถึงตอนนี้ หากคุณต้องการเฟรมเวิร์กในการทำงานหนัก ๆ คุณสามารถขยาย SQL Mapper ได้โดยการประกาศชั้นเรียนของคุณเองด้วยวิธีการที่กำหนดเอง- แต่คุณไม่สามารถหลีกเลี่ยงการได้รับมือของคุณเลี่ยนบน SQL ที่ไม่ยอมใครง่ายๆ:-
class Vendor extends DB SQL Mapper {
// Instantiate mapper
function __construct ( DB SQL $ db ) {
// This is where the mapper and DB structure synchronization occurs
parent :: __construct ( $ db , ' vendors ' );
}
// Specialized query
function listByCity () {
return $ this -> select (
' vendorID,name,city ' ,[ ' order ' => ' city DESC ' ]);
/ *
We could have done the the same thing with plain vanilla SQL : -
return $ this - > db - > exec (
'SELECT vendorID,name,city FROM vendors ' .
'ORDER BY city DESC;'
);
* /
}
}
$ vendor = new Vendor ;
$ vendor -> listByCity ();
การขยายข้อมูลแม็ปเปอร์ในแบบนี้เป็นวิธีที่ง่ายในการสร้างโมเดลที่เกี่ยวข้องกับ DB ของแอปพลิเคชัน
หากคุณมีประโยชน์กับ SQL คุณอาจจะพูดว่า: ทุกอย่างใน ORM สามารถจัดการได้ด้วยการสืบค้น SQL แบบโรงเรียนเก่า อย่างแท้จริง. เราสามารถทำได้โดยไม่ต้องมีผู้ฟังเหตุการณ์เพิ่มเติมโดยใช้ทริกเกอร์ฐานข้อมูลและขั้นตอนที่เก็บไว้ เราสามารถทำแบบสอบถามเชิงสัมพันธ์กับตารางที่เข้าร่วมได้ ORM เป็นค่าใช้จ่ายที่ไม่จำเป็น แต่ประเด็นก็คือ - ตัวแมปข้อมูลให้ฟังก์ชันการทำงานที่เพิ่มขึ้นของการใช้วัตถุเพื่อแสดงเอนทิตีฐานข้อมูล ในฐานะนักพัฒนาคุณสามารถเขียนโค้ดได้เร็วขึ้นและมีประสิทธิผลมากขึ้น โปรแกรมผลลัพธ์จะสะอาดกว่านี้หากไม่สั้นลง แต่คุณจะต้องชั่งน้ำหนักผลประโยชน์กับการประนีประนอมด้วยความเร็ว - โดยเฉพาะอย่างยิ่งเมื่อจัดการกับที่เก็บข้อมูลขนาดใหญ่และซับซ้อน โปรดจำไว้ว่า ORMS ทั้งหมด - ไม่ว่าพวกเขาจะผอมแค่ไหน - จะเป็นเพียงชั้นนามธรรมอื่นเสมอ พวกเขายังคงต้องผ่านงานไปยังเครื่องยนต์ SQL พื้นฐาน
โดยการออกแบบ ORM ของ F3 ไม่ได้ให้วิธีการเชื่อมต่อวัตถุโดยตรงกับกันและกันเช่น SQL เข้าร่วม - เพราะสิ่งนี้จะเปิดกระป๋องของเวิร์ม มันทำให้แอปพลิเคชันของคุณซับซ้อนกว่าที่ควรจะเป็นและมีแนวโน้มของวัตถุที่ผ่านความกระตือรือร้นหรือเทคนิคการดึงที่ขี้เกียจที่จะหยุดชะงักและแม้กระทั่งการซิงค์เนื่องจากการสืบทอดวัตถุและ polymorphism (ความต้านทานไม่ตรงกัน) กับเอนทิตีฐานข้อมูล . มีวิธีทางอ้อมในการทำใน SQL Mapper โดยใช้ฟิลด์เสมือนจริง - แต่คุณจะต้องทำสิ่งนี้โดยทางโปรแกรมและความเสี่ยงของคุณเอง
หากคุณถูกล่อลวงให้ใช้แนวคิด OOP "บริสุทธิ์" ในแอปพลิเคชันของคุณเพื่อแสดงข้อมูลทั้งหมดของคุณ (เพราะ "ทุกอย่างเป็นวัตถุ") โปรดทราบว่าข้อมูลเกือบจะมีชีวิตอยู่นานกว่าแอปพลิเคชันเกือบทุกครั้ง โปรแกรมของคุณอาจล้าสมัยไปแล้วก่อนที่ข้อมูลจะสูญเสียมูลค่า อย่าเพิ่มความซับซ้อนอีกชั้นในโปรแกรมของคุณโดยใช้วัตถุและคลาสที่เชื่อมโยงกันซึ่งเบี่ยงเบนมากเกินไปจากสคีมาและโครงสร้างทางกายภาพของข้อมูล
ก่อนที่คุณจะสานวัตถุหลายชิ้นเข้าด้วยกันในแอปพลิเคชันของคุณเพื่อจัดการตารางพื้นฐานในฐานข้อมูลของคุณลองคิดดู: การสร้างมุมมองเพื่อแสดงถึงความสัมพันธ์และทริกเกอร์เพื่อกำหนดพฤติกรรมของวัตถุในเอ็นจินฐานข้อมูลมีประสิทธิภาพมากขึ้น เอ็นจิ้นฐานข้อมูลเชิงสัมพันธ์ได้รับการออกแบบมาเพื่อจัดการกับมุมมองตารางและทริกเกอร์ พวกเขาไม่ใช่ที่เก็บข้อมูลใบ้ ตารางที่เข้าร่วมในมุมมองจะปรากฏเป็นตารางเดียวและปลอดไขมันสามารถแมปอัตโนมัติมุมมองได้เช่นเดียวกับตารางปกติ การทำซ้ำการรวมเป็นวัตถุเชิงสัมพันธ์ใน PHP ช้ากว่าเมื่อเทียบกับรหัสเครื่องของเอ็นจิ้นฐานข้อมูลพีชคณิตเชิงสัมพันธ์และตรรกะการเพิ่มประสิทธิภาพ นอกจากนี้การเข้าร่วมตารางซ้ำ ๆ ในแอปพลิเคชันของเราเป็นสัญญาณที่แน่นอนว่าการออกแบบฐานข้อมูลจำเป็นต้องได้รับการตรวจสอบและมุมมองถือว่าเป็นส่วนสำคัญของการดึงข้อมูล หากตารางข้อมูลอ้างอิงข้ามจากตารางอื่นบ่อยครั้งให้พิจารณาการทำให้โครงสร้างของคุณเป็นปกติหรือสร้างมุมมองแทน จากนั้นสร้างวัตถุ Mapper เพื่อทำแผนที่อัตโนมัติมุมมองนั้น มันเร็วขึ้นและต้องใช้ความพยายามน้อยลง
พิจารณามุมมอง SQL นี้ที่สร้างขึ้นภายในเอ็นจินฐานข้อมูลของคุณ:-
CREATE VIEW combined AS
SELECT
projects . project_id AS project,
users . name AS name
FROM projects
LEFT OUTER JOIN users ON
projects . project_id = users . project_id AND
projects . user_id = users . user_id ;
รหัสแอปพลิเคชันของคุณง่ายขึ้นเพราะไม่จำเป็นต้องรักษาวัตถุแผนที่สองชิ้น (หนึ่งรายการสำหรับตารางโครงการและอีกอันสำหรับผู้ใช้) เพียงเพื่อดึงข้อมูลจากสองตารางที่เข้าร่วม:-
$ combined = new DB SQL Mapper ( $ db , ' combined ' );
$ combined -> load ([ ' project=? ' , 123 ]);
echo $ combined -> name ;
เคล็ดลับ: ใช้เครื่องมือตามที่ออกแบบมา Fat Free มีผู้ช่วย SQL ที่ใช้งานง่ายแล้ว ใช้ถ้าคุณต้องการค้อนที่ใหญ่กว่า :) พยายามหาสมดุลระหว่างความสะดวกและประสิทธิภาพ SQL will always be your fallback if you're working on complex and legacy data structures.
Plug-ins are nothing more than autoloaded classes that use framework built-ins to extend F3's features and functionality. If you'd like to contribute, leave a note at the Fat-Free Discussion Area hosted by Google Groups or tell us about it in the FreeNode #fatfree
IRC channel. Someone else might be involved in a similar project. The framework community will appreciate it a lot if we unify our efforts.
There might be instances when you want to make your forms more secure against spam bots and malicious automated scripts. F3 provides a captcha()
method to generate images with random text that are designed to be recognizable only by humans.
$ img = new Image ();
$ img -> captcha ( ' fonts/CoolFont.ttf ' , 16 , 5 , ' SESSION.captcha_code ' );
$ img -> render ();
This example generates an random image based on your desired TrueType font. The fonts/
folder is a subfolder within application's UI
path. The second parameter indicates the font size, and the third argument defines the number of hexadecimal characters to generate.
The last argument represents an F3 variable name. This is where F3 will store the string equivalent of the CAPTCHA image. To make the string reload-safe, we specified a session variable:- SESSION.captcha_code
which maps to $_SESSION['captcha_code']
, which you can use later to verify whether the input element in the form submitted matches this string.
We've covered almost every feature available in the framework to run a stand-alone Web server. For most applications, these features will serve you quite well. But what do you do if your application needs data from another Web server on the network? F3 has the Web plugin to help you in this situation:-
$ web = new Web ;
$ request = $ web -> request ( ' http://www.google.com/ ' );
// another way to do it : -
$ request =Web:: instance ()-> request ( ' http://www.google.com/ ' );
This simple example sends an HTTP request to the page located at www.google.com and stores it in the $request
PHP variable. The request()
method returns an array containing the HTTP response such that $request['headers']
and $request['body']
represent the response headers and body, respectively. We could have saved the contents using the F3::set command, or echo'ed the output directly to our browser. Retrieving another HTML page on the net may not have any practical purpose. But it can be particularly useful in ReSTful applications, like querying a CouchDB server.
$ host = ' localhost:5984 ' ;
$ web -> request ( $ host . ' /_all_dbs ' ),
$ web -> request ( $ host . ' /testdb/ ' ,[ ' method ' => ' PUT ' ]);
You may have noticed that you can pass an array of additional options to the request()
method:-
$ web -> request (
' https://www.example.com:443? ' .
http_build_query (
[
' key1 ' => ' value1 ' ,
' key2 ' => ' value2 '
]
),
[
' headers ' =>[
' Accept: text/html,application/xhtml+xml,application/xml ' ,
' Accept-Language: en-us '
],
' follow_location ' => FALSE ,
' max_redirects ' => 30 ,
' ignore_errors ' => TRUE
]
);
If the framework variable CACHE
is enabled, and if the remote server instructs your application to cache the response to the HTTP request, F3 will comply with the request and retrieve the cached response each time the framework receives a similar request from your application, thus behaving like a browser.
Fat-Free will use whatever means are available on your Web server for the request()
method to run: PHP stream wrappers ( allow_url_fopen
), cURL module, or low-level sockets.
F3 has a utility for sending files to an HTTP client, ie fulfilling download requests. You can use it to hide the real path to your download files. This adds some layer of security because users won't be able to download files if they don't know the file names and their locations. Here's how it's done:-
$ f3 -> route ( ' GET /downloads/@filename ' ,
function ( $ f3 , $ args ) {
// send () method returns FALSE if file doesn ' t exist
if (!Web:: instance ()-> send ( ' /real/path/ ' . $ args [ ' filename ' ]))
// Generate an HTTP 404
$ f3 -> error ( 404 );
}
);
The request()
method can also be used in complex SOAP or XML-RPC applications, if you find the need for another Web server to process data on your computer's behalf - thus harnessing the power of distributing computing. W3Schools.com has an excellent tutorial on SOAP. On the other hand, TutorialsPoint.com gives a nice overview of XML-RPC.
Caching static Web pages - so the code in some route handlers can be skipped and templates don't have to be reprocessed - is one way of reducing your Web server's work load so it can focus on other tasks. You can activate the framework's cache engine by providing a third argument to the $f3->route()
method. Just specify the number of seconds before a cached Web page expires:-
$ f3 -> route ( ' GET /my_page ' , ' App->method ' , 60 );
นี่คือวิธีการทำงาน In this example, when F3 detects that the URL /my_page
is accessed for the first time, it executes the route handler represented by the second argument and saves all browser output to the framework's built-in cache (server-side). A similar instruction is automatically sent to the user's Web browser (client-side), so that instead of sending an identical request to the server within the 60-second period, the browser can just retrieve the page locally. The framework uses the cache for an entirely different purpose - serving framework-cached data to other users asking for the same Web page within the 60-second time frame. It skips execution of the route handler and serves the previously-saved page directly from disk. When someone tries to access the same URL after the 60-second timer has lapsed, F3 will refresh the cache with a new copy.
Web pages with static data are the most likely candidates for caching. Fat-Free will not cache a Web page at a specified URL if the third argument in the $f3->route()
method is zero or unspecified. F3 conforms to the HTTP specifications: only GET and HEAD requests can be cached.
Here's an important point to consider when designing your application. Don't cache Web pages unless you understand the possible unwanted side-effects of the cache at the client-side. Make sure that you activate caching on Web pages that have nothing to do with the user's session state.
For example, you designed your site in such a way that all your Web pages have the menu options: "Home"
, "About Us"
, and "Login"
, displayed when a user is not logged into your application. You also want the menu options to change to: "Home"
, "About Us"
, and "Logout"
, once the user has logged in. If you instructed Fat-Free to cache the contents of "About Us"
page (which includes the menu options), it does so and also sends the same instruction to the HTTP client. Regardless of the user's session state, ie logged in or logged out, the user's browser will take a snapshot of the page at the session state it was in. Future requests by the user for the "About Us"
page before the cache timeout expires will display the same menu options available at that time the page was initially saved. Now, a user may have already logged in, but the menu options are still the same as if no such event occurred. That's not the kind of behavior we want from our application.
Some pointers:-
GET
routes only. It will not cache submitted forms!Don't activate the cache on Web pages that at first glance look static. In our example, the "About Us" content may be static, but the menu isn't."About Us"
page, make sure it's available only when a user is not logged in.CACHE
global variable so it points to that drive. This will make your application run like a Formula 1 race car. Note: Don't set the timeout value to a very long period until you're ready to roll out your application, ie the release or production state. Changes you make to any of your PHP scripts may not have the expected effect on the displayed output if the page exists in the framework cache and the expiration period has not lapsed. If you do alter a program that generates a page affected by the cache timer and you want these changes to take effect immediately, you should clear the cache by erasing the files in the cache/ directory (or whatever path the CACHE
global variable points to) . F3 will automatically refresh the cache if necessary. At the client-side, there's little you can do but instruct the user to clear the browser's cache or wait for the cache period to expire.
PHP needs to be set up correctly for the F3 cache engine to work properly. Your operating system timezone should be synchronized with the date.timezone setting in the php.ini
file.
Similar to routes, Fat-Free also allows you to cache database queries. Speed gains can be quite significant, specially when used on complex SQL statements that involve look-up of static data or database content that rarely changes. Activating the database query cache so the framework doesn't have to re-execute the SQL statements every time is as simple as adding a 3rd argument to the F3::sql command - the cache timeout. ตัวอย่างเช่น:-
$ db -> exec ( ' SELECT * from sizes; ' , NULL , 86400 );
If we expect the result of this database query to always be Small
, Medium
, and Large
within a 24-hour period, we specify 86400
seconds as the 2nd argument so Fat-Free doesn't have to execute the query more than once a day . Instead, the framework will store the result in the cache, retrieve it from the cache every time a request comes in during the specified 24-hour time frame, and re-execute the query when the timer lapses.
The SQL data mapper also uses the cache engine to optimize synchronization of table structures with the objects that represent them. The default is 60
seconds. If you make any changes to a table's structure in your database engine, you'll have to wait for the cache timer to expire before seeing the effect in your application. You can change this behavior by specifying a third argument to the data mapper constructor. Set it to a high value if you don't expect to make any further changes to your table structure.
$ user = new DB SQL Mapper ( $ db , ' users ' , 86400 );
By default, Fat-Free's cache engine is disabled. You can enable it and allow it to auto-detect APC, WinCache or XCache. If it cannot find an appropriate backend, F3 will use the filesystem, ie the tmp/cache/
folder:-
$ f3 -> set ( ' CACHE ' , TRUE );
Disabling the cache is as simple as:-
$ f3 -> set ( ' CACHE ' , FALSE );
If you wish to override the auto-detection feature, you can do so - as in the case of a Memcached back-end which F3 also supports:-
$ f3 -> set ( ' CACHE ' , ' memcache=localhost:11211 ' );
You can also use the cache engine to store your own variables. These variables will persist between HTTP requests and remain in cache until the engine receives instructions to delete them. To save a value in the cache:-
$ f3 -> set ( ' var ' , ' I want this value saved ' , 90 );
$f3->set()
method's third argument instructs the framework to save the variable in the cache for a 90-second duration. If your application issues a $f3->get('var')
within this period, F3 will automatically retrieve the value from cache. In like manner, $f3->clear('var')
will purge the value from both cache and RAM. If you want to determine if a variable exists in cache, `$f3->exists('var')); returns one of two possible values: FALSE if the framework variable passed does not exist in cache, or an integer representing the time the variable was saved (Un*x time in seconds, with microsecond precision).
Fat-Free also has a Javascript and CSS compressor available in the Web plug-in. It can combine all your CSS files into one stylesheet (or Javascript files into a single script) so the number of components on a Web page are decreased. Reducing the number of HTTP requests to your Web server results in faster page loading. First you need to prepare your HTML template so it can take advantage of this feature. Something like:-
< link rel =" stylesheet " type =" text/css "
href =" /minify/css?files=typo.css,grid.css " />
Do the same with your Javascript files:-
< script type =" text/javascript " src =" /minify/js?&files=underscore.js " >
</ script >
Of course we need to set up a route so your application can handle the necessary call to the Fat-Free CSS/Javascript compressor:-
$ f3 -> route ( ' GET /minify/@type ' ,
function ( $ f3 , $ args ) {
$ f3 -> set ( ' UI ' , $ args [ ' type ' ]. ' / ' );
echo Web:: instance ()-> minify ( $ _GET [ ' files ' ]);
},
3600
);
And that's all there is to it! minify()
reads each file ( typo.css
and grid.css
in our CSS example, underscore.js
in our Javascript example), strips off all unnecessary whitespaces and comments, combines all of the related items as a single Web page component, and attaches a far-future expiry date so the user's Web browser can cache the data. It's important that the PARAMS.type
variable base points to the correct path. Otherwise, the URL rewriting mechanism inside the compressor won't find the CSS/Javascript files.
In our examples, the framework sends a far-future expiry date to the client's Web browser so any request for the same CSS or Javascript block will come from the user's hard drive. On the server side, F3 will check each request and see if the CSS or Javascript blocks have already been cached. The route we specified has a cache refresh period of 3600
seconds. Additionally, if the Web browser sends an If-Modified-Since
request header and the framework sees the cache hasn't changed, F3 just sends an HTTP 304 Not Modified
response so no content is actually delivered. Without the If-Modified-Since
header, Fat-Free renders the output from the cached file if available. Otherwise, the relevant code is executed.
Tip: If you're not modifying your Javascript/CSS files frequently (as it would be if you're using a Javascript library like jQuery, MooTools, Dojo, etc.), consider adding a cache timer to the route leading to your Javascript/CSS minify handler (3rd argument of F3::route()) so Fat-Free doesn't have compress and combine these files each time such a request is received.
Want to make your site run even faster? Fat-Free works best with either Alternative PHP Cache (APC), XCache, or WinCache. These PHP extensions boost performance of your application by optimizing your PHP scripts (including the framework code).
A fast application that processes all HTTP requests and responds to them at the shortest time possible is not always a good idea - specially if your bandwidth is limited or traffic on your Web site is particularly heavy. Serving pages ASAP also makes your application vulnerable to Denial-of-Service (DOS) attacks. F3 has a bandwidth throttling feature that allows you to control how fast your Web pages are served. You can specify how much time it should take to process a request:-
$ f3 -> route ( ' /throttledpage ' , ' MyApp->handler ' , 0 , 128 );
In this example, the framework will serve the Web page at a rate of 128KiBps.
Bandwidth throttling at the application level can be particularly useful for login pages. Slow responses to dictionary attacks is a good way of mitigating this kind of security risk.
Robust applications are the result of comprehensive testing. Verifying that each part of your program conforms to the specifications and lives up to the expectations of the end-user means finding bugs and fixing them as early as possible in the application development cycle.
If you know little or nothing about unit testing methodologies, you're probably embedding pieces of code directly in your existing program to help you with debugging. That of course means you have to remove them once the program is running. Leftover code fragments, poor design and faulty implementation can creep up as bugs when you roll out your application later.
F3 makes it easy for you to debug programs - without getting in the way of your regular thought processes. The framework does not require you to build complex OOP classes, heavy test structures, and obtrusive procedures.
A unit (or test fixture) can be a function/method or a class. Let's have a simple example:-
function hello () {
return ' Hello, World ' ;
}
Save it in a file called hello.php
. Now how do we know it really runs as expected? Let's create our test procedure:-
$ f3 = require ( ' lib/base.php ' );
// Set up
$ test = new Test ;
include ( ' hello.php ' );
// This is where the tests begin
$ test -> expect (
is_callable ( ' hello ' ),
' hello() is a function '
);
// Another test
$ hello = hello ();
$ test -> expect (
! empty ( $ hello ),
' Something was returned '
);
// This test should succeed
$ test ->expect
is_string ( $ hello ),
' Return value is a string '
);
// This test is bound to fail
$ test -> expect (
strlen ( $ hello )== 13 ,
' String length is 13 '
);
// Display the results ; not MVC but let ' s keep it simple
foreach ( $ test -> results () as $ result ) {
echo $ result [ ' text ' ]. ' <br /> ' ;
if ( $ result [ ' status ' ])
echo ' Pass ' ;
else
echo ' Fail ( ' . $ result [ ' source ' ]. ' ) ' ;
echo ' <br /> ' ;
}
Save it in a file called test.php
. This way we can preserve the integrity of hello.php
.
Now here's the meat of our unit testing process.
F3's built-in Test
class keeps track of the result of each expect()
call. The output of $test->results()
is an array of arrays with the keys text
(mirroring argument 2 of expect()
), status
(boolean representing the result of a test), and source
(file name/line number of the specific test) to aid in debugging.
Fat-Free gives you the freedom to display test results in any way you want. You can have the output in plain text or even a nice-looking HTML template. So how do we run our unit test? If you saved test.php
in the document root folder, you can just open your browser and specify the address http://localhost/test.php
. นั่นคือทั้งหมดที่มีให้มัน
F3 gives you the ability to simulate HTTP requests from within your PHP program so you can test the behavior of a particular route. Here's a simple mock request:-
$ f3 -> mock ( ' GET /test?foo=bar ' );
To mock a POST request and submit a simulated HTML form:-
$ f3 -> mock ( ' POST /test ' ,[ ' foo ' => ' bar ' ]);
Once you get the hang of testing the smallest units of your application, you can then move on to the bigger components, modules, and subsystems - checking along the way if the parts are correctly communicating with each other. Testing manageable chunks of code leads to more reliable programs that work as you expect, and weaves the testing process into the fabric of your development cycle. The question to ask yourself is:- Have I tested all possible scenarios? More often than not, those situations that have not been taken into consideration are the likely causes of bugs. Unit testing helps a lot in minimizing these occurrences. Even a few tests on each fixture can greatly reduce headaches. On the other hand, writing applications without unit testing at all invites trouble.
string AGENT
Mozilla/5.0 (Linux; Android 4.2.2; Nexus 7) AppleWebKit/537.31
. bool AJAX
TRUE
if an XML HTTP request is detected, FALSE
otherwise. string AUTOLOAD
|
), comma ( ,
), or semi-colon ( ;
) as path separator. string BASE
index.php
main/front controller. string BODY
bool/string CACHE
'memcache=localhost'
(and the PHP memcache module is present), F3 auto-detects the presence of APC, WinCache and XCache and uses the first available PHP module if set to TRUE. If none of these PHP modules are available, a filesystem-based backend is used (default directory: tmp/cache
). The framework disables the cache engine if assigned a FALSE
value. bool CASELESS
FALSE
to make it case-sensitive. array COOKIE, GET, POST, REQUEST, SESSION, FILES, SERVER, ENV
integer DEBUG
string DNSBL
403 Forbidden
error if the user's IPv4 address is listed on the specified server(s). array DIACRITICS
string ENCODING
UTF-8
. array ERROR
ERROR.code
is the HTTP status code. ERROR.status
contains a brief description of the error. ERROR.text
provides more detail. For HTTP 500 errors, use ERROR.trace
to retrieve the stack trace. bool ESCAPE
string EXEMPT
string FALLBACK
bool HALT
array HEADERS
bool HIGHLIGHT
TRUE
(requires code.css
stylesheet). string HOST
$_SERVER['SERVER_NAME']
is not available, return value of gethostname()
is used. string IP
array JAR
string LANGUAGE
LOCALES
. If set to NULL
, language is auto-detected from the HTTP Accept-Language
request header. string LOCALES
string LOGS
mixed ONERROR
string PACKAGE
array PARAMS
route()
pattern. PARAMS.0
contains the captured URL relative to the Web root. string PATTERN
string PLUGINS
base.php
. int PORT
string PREFIX
bool QUIET
bool RAW
BODY
. Should be TRUE when processing large data coming from php://input
which will not fit in memory. Default value: FALSE
string REALM
string RESPONSE
QUIET
setting. string ROOT
array ROUTES
string SCHEME
http
or https
. string SERIALIZER
php
, unless PHP igbinary
extension is auto-detected. Assign json
if desired. string TEMP
tmp/
folder inside the Web root. Adjust accordingly to conform to your site's security policies. string TZ
date_default_timezone_set()
function. string UI
View
and Template
classes' render()
method. Default value is the Web root. Accepts a pipe ( |
), comma ( ,
), or semi-colon ( ;
) as separator for multiple paths. callback UNLOAD
string UPLOADS
string URI
string VERB
string VERSION
@token
@token
with value of equivalent F3 variable. {{ mixed expr }}
expr
may include template tokens, constants, operators (unary, arithmetic, ternary and relational), parentheses, data type converters, and functions. If not an attribute of a template directive, result is echoed. {{ string expr | raw }}
expr
. F3 auto-escapes strings by default. {{ string expr | esc }}
expr
. This is the default framework behavior. | esc
suffix is only necessary if ESCAPE
global variable is set to FALSE
. {{ string expr, arg1, ..., argN | format }}
expr
and pass the comma-separated arguments, where arg1, ..., argn
is one of:- 'date'
, 'time'
, 'number, integer'
, 'number, currency'
, or 'number, percent'
. <include
[ if="{{ bool condition }}" ]
href="{{ string subtemplate }}"
/>
subtemplate
and insert at current position in template if optional condition is TRUE
. <exclude>text-block</exclude>
text-block
at runtime. Used for embedding comments in templates. <ignore>text-block</ignore>
text-block
as-is, without interpretation/modification by the template engine. <check if="{{ bool condition }}">
<true>true-block</true>
<false>false-block</false>
</check>
TRUE
, then true-block
is rendered. Otherwise, false-block
is used. <loop
from="{{ statement }}"
to="{{ bool expr }}"
[ step="{{ statement }}" ]>
text-block
</loop>
from
statement once. Check if the expression in the to
attribute is TRUE
, render text-block
and evaluate step
statement. Repeat iteration until to
expression is FALSE
. <repeat
group="{{ array @group|expr }}"
[ key="{{ scalar @key }}" ]
value="{{ mixed @value }}"
[ counter="{{ scalar @key }}" ]>
text-block
</repeat>
text-block
as many times as there are elements in the array variable @group
or the expression expr
. @key
and @value
function in the same manner as the key-value pair in the equivalent PHP foreach()
statement. Variable represented by key
in counter
attribute increments by 1
with every iteration. <switch expr="{{ scalar expr }}">
<case value="{{ scalar @value|expr }}" break="{{ bool TRUE|FALSE }}">
text-block
</case>
.
.
.
</switch>
{* text-block *}
<exclude>
.The most up-to-date documentation is located at http://fatfreeframework.com/. It contains examples of usage of the various framework components.
Technical support is available at the official discussion forum: https://groups.google.com/forum/#!forum/f3-framework
. If you need live support, you can talk to the development team and other members of the F3 community via Slack or IRC. We're on the FreeNode #fatfree
channel ( chat.freenode.net
). Visit http://webchat.freenode.net/
to join the conversation. You can also download the Firefox Chatzilla add-on or Pidgin if you don't have an IRC client so you can participate in the live chat. You can also find help at Stack Overflow
F3 uses Git for version control. To clone the latest code repository on GitHub:
git clone git://github.com/bcosca/fatfree-core.git
If all you want is a zipball of our test bench with all unit tests, grab it here .
To file a bug report, visit https://github.com/bcosca/fatfree-core/issues
.
Fat-Free Framework is free and released as open source software covered by the terms of the GNU Public License (GPL v3). You may not use the software, documentation, and samples except in compliance with the license. If the terms and conditions of this license are too restrictive for your use, alternative licensing is available for a very reasonable fee.
If you feel that this software is one great weapon to have in your programming arsenal, it saves you a lot of time and money, use it for commercial gain or in your business organization, please consider making a donation to the project. A significant amount of time, effort, and money has been spent on this project. Your donations help keep this project alive and the development team motivated. Donors and sponsors get priority support (24-hour response time on business days).
The Fat-Free Framework is community-driven software. It can't be what it is today without the help and support from the following people and organizations:
Special thanks to the selfless others who expressed their desire to remain anonymous, yet share their time, contribute code, send donations, promote the framework to a wider audience, as well as provide encouragement and regular financial assistance. Their generosity is F3's prime motivation.
By making a donation to this project you signify that you acknowledged, understood, accepted, and agreed to the terms and conditions contained in this notice. Your donation to the Fat-Free Framework project is voluntary and is not a fee for any services, goods, or advantages, and making a donation to the project does not entitle you to any services, goods, or advantages. We have the right to use the money you donate to the Fat-Free Framework project in any lawful way and for any lawful purpose we see fit and we are not obligated to disclose the way and purpose to any party unless required by applicable law. Although Fat-Free Framework is free software, to our best knowledge this project does not have any tax-exempt status. The Fat-Free Framework project is neither a registered non-profit corporation nor a registered charity in any country. Your donation may or may not be tax-deductible; please consult this with your tax advisor. We will not publish/disclose your name and e-mail address without your consent, unless required by applicable law. Your donation is non-refundable.
Copyright (c) 2009-2022 F3::Factory/Bong Cosca <[email protected]>
Hey dude! Help me out for a couple of !