ฉันคิดว่าตัวเลือกที่ดีที่สุดคือจุดสิ้นสุด คุณได้รับข้อมูลทั้งหมดเป็นสตริงอย่างง่ายดังนั้นคุณสามารถตัดสินใจได้ว่าจะแยกวิเคราะห์อย่างไรและคุณไม่ต้องกังวลเกี่ยวกับการชนกับกฎการเขียนซ้ำอื่น ๆ
สิ่งหนึ่งที่ฉันได้เรียนรู้เกี่ยวกับจุดปลาย: ทำให้งานหลักเป็นนามธรรมที่สุดแก้ไขข้อบกพร่องใน WordPress 'API ในแบบไม่เชื่อเรื่องพระเจ้า
ฉันจะแยกตรรกะออกเป็นสามส่วน: ตัวควบคุมเลือกรูปแบบและมุมมองแบบจำลองเพื่อจัดการจุดปลายและอีกหนึ่งมุมมองเพื่อส่งคืนข้อมูลที่มีประโยชน์หรือข้อความแสดงข้อผิดพลาด
ตัวควบคุม
เริ่มจากตัวควบคุมกันก่อน มันไม่ได้ทำอะไรมากมายดังนั้นฉันจึงใช้ฟังก์ชั่นที่ง่ายมากที่นี่:
add_action( 'plugins_loaded', 't5_cra_init' );
function t5_cra_init()
{
require dirname( __FILE__ ) . '/class.T5_CRA_Model.php';
$options = array (
'callback' => array ( 'T5_CRA_View_Demo', '__construct' ),
'name' => 'api',
'position' => EP_ROOT
);
new T5_CRA_Model( $options );
}
โดยพื้นฐานแล้วมันจะโหลดโมเดลT5_CRA_Model
และส่งมอบพารามิเตอร์บางอย่าง…และงานทั้งหมด คอนโทรลเลอร์ไม่ทราบอะไรเกี่ยวกับตรรกะภายในของโมเดลหรือมุมมอง มันแค่เกาะติดกันทั้งคู่ นี่เป็นส่วนเดียวที่คุณไม่สามารถใช้ซ้ำได้ นั่นเป็นเหตุผลที่ฉันเก็บมันแยกออกจากส่วนอื่น ๆ
ตอนนี้เราต้องการคลาสอย่างน้อยสองคลาส: โมเดลที่ลงทะเบียน API และมุมมองเพื่อสร้างเอาต์พุต
นางแบบ
ชั้นนี้จะ:
- ลงทะเบียนจุดสิ้นสุด
- เคสที่มีปลายทางถูกเรียกโดยไม่มีพารามิเตอร์เพิ่มเติมใด ๆ
- เติมกฎการเขียนซ้ำที่หายไปเนื่องจากข้อบกพร่องบางอย่างในรหัสของบุคคลที่สาม
- แก้ไขข้อผิดพลาด WordPress ด้วยหน้าคงที่และจุดสิ้นสุดสำหรับ
EP_ROOT
- แยก URI เป็นอาร์เรย์ (ซึ่งสามารถแยกได้ด้วย)
- เรียกใช้ตัวจัดการการเรียกกลับด้วยค่าเหล่านั้น
ฉันหวังว่ารหัสพูดสำหรับตัวเอง :)
ตัวแบบไม่รู้อะไรเลยเกี่ยวกับโครงสร้างด้านในของข้อมูลหรือการนำเสนอ ดังนั้นคุณสามารถใช้มันเพื่อลงทะเบียน API หลายร้อยรายการโดยไม่ต้องเปลี่ยนหนึ่งบรรทัด
<?php # -*- coding: utf-8 -*-
/**
* Register new REST API as endpoint.
*
* @author toscho http://toscho.de
*
*/
class T5_CRA_Model
{
protected $options;
/**
* Read options and register endpoint actions and filters.
*
* @wp-hook plugins_loaded
* @param array $options
*/
public function __construct( Array $options )
{
$default_options = array (
'callback' => array ( 'T5_CRA_View_Demo', '__construct' ),
'name' => 'api',
'position' => EP_ROOT
);
$this->options = wp_parse_args( $options, $default_options );
add_action( 'init', array ( $this, 'register_api' ), 1000 );
// endpoints work on the front end only
if ( is_admin() )
return;
add_filter( 'request', array ( $this, 'set_query_var' ) );
// Hook in late to allow other plugins to operate earlier.
add_action( 'template_redirect', array ( $this, 'render' ), 100 );
}
/**
* Add endpoint and deal with other code flushing our rules away.
*
* @wp-hook init
* @return void
*/
public function register_api()
{
add_rewrite_endpoint(
$this->options['name'],
$this->options['position']
);
$this->fix_failed_registration(
$this->options['name'],
$this->options['position']
);
}
/**
* Fix rules flushed by other peoples code.
*
* @wp-hook init
* @param string $name
* @param int $position
*/
protected function fix_failed_registration( $name, $position )
{
global $wp_rewrite;
if ( empty ( $wp_rewrite->endpoints ) )
return flush_rewrite_rules( FALSE );
foreach ( $wp_rewrite->endpoints as $endpoint )
if ( $endpoint[0] === $position && $endpoint[1] === $name )
return;
flush_rewrite_rules( FALSE );
}
/**
* Set the endpoint variable to TRUE.
*
* If the endpoint was called without further parameters it does not
* evaluate to TRUE otherwise.
*
* @wp-hook request
* @param array $vars
* @return array
*/
public function set_query_var( Array $vars )
{
if ( ! empty ( $vars[ $this->options['name'] ] ) )
return $vars;
// When a static page was set as front page, the WordPress endpoint API
// does some strange things. Let's fix that.
if ( isset ( $vars[ $this->options['name'] ] )
or ( isset ( $vars['pagename'] ) and $this->options['name'] === $vars['pagename'] )
or ( isset ( $vars['page'] ) and $this->options['name'] === $vars['name'] )
)
{
// In some cases WP misinterprets the request as a page request and
// returns a 404.
$vars['page'] = $vars['pagename'] = $vars['name'] = FALSE;
$vars[ $this->options['name'] ] = TRUE;
}
return $vars;
}
/**
* Prepare API requests and hand them over to the callback.
*
* @wp-hook template_redirect
* @return void
*/
public function render()
{
$api = get_query_var( $this->options['name'] );
$api = trim( $api, '/' );
if ( '' === $api )
return;
$parts = explode( '/', $api );
$type = array_shift( $parts );
$values = $this->get_api_values( join( '/', $parts ) );
$callback = $this->options['callback'];
if ( is_string( $callback ) )
{
call_user_func( $callback, $type, $values );
}
elseif ( is_array( $callback ) )
{
if ( '__construct' === $callback[1] )
new $callback[0]( $type, $values );
elseif ( is_callable( $callback ) )
call_user_func( $callback, $type, $values );
}
else
{
trigger_error(
'Cannot call your callback: ' . var_export( $callback, TRUE ),
E_USER_ERROR
);
}
// Important. WordPress will render the main page if we leave this out.
exit;
}
/**
* Parse request URI into associative array.
*
* @wp-hook template_redirect
* @param string $request
* @return array
*/
protected function get_api_values( $request )
{
$keys = $values = array();
$count = 0;
$request = trim( $request, '/' );
$tok = strtok( $request, '/' );
while ( $tok !== FALSE )
{
0 === $count++ % 2 ? $keys[] = $tok : $values[] = $tok;
$tok = strtok( '/' );
}
// fix odd requests
if ( count( $keys ) !== count( $values ) )
$values[] = '';
return array_combine( $keys, $values );
}
}
มุมมอง
ตอนนี้เราต้องทำอะไรกับข้อมูลของเรา นอกจากนี้เรายังสามารถจับข้อมูลที่ขาดหายไปสำหรับคำขอที่ไม่สมบูรณ์หรือมอบหมายการจัดการให้กับมุมมองหรือตัวควบคุมย่อยอื่น ๆ
นี่เป็นตัวอย่างง่ายๆ:
class T5_CRA_View_Demo
{
protected $allowed_types = array (
'plain',
'html',
'xml'
);
protected $default_values = array (
'country' => 'Norway',
'date' => 1700,
'max' => 200
);
public function __construct( $type, $data )
{
if ( ! in_array( $type, $this->allowed_types ) )
die( 'Your request is invalid. Please read our fantastic manual.' );
$data = wp_parse_args( $data, $this->default_values );
header( "Content-Type: text/$type;charset=utf-8" );
$method = "render_$type";
$this->$method( $data );
}
protected function render_plain( $data )
{
foreach ( $data as $key => $value )
print "$key: $value\n";
}
protected function render_html( $data ) {}
protected function render_xml( $data ) {}
}
ส่วนที่สำคัญคือมุมมองไม่รู้อะไรเกี่ยวกับจุดสิ้นสุด คุณสามารถใช้มันเพื่อจัดการแสดงที่แตกต่างกันอย่างสมบูรณ์สำหรับการร้องขอเช่น AJAX wp-admin
ใน คุณสามารถแยกมุมมองออกเป็นรูปแบบ MVC ของตัวเองหรือใช้เพียงฟังก์ชั่นง่ายๆ