問題描述
我的問題是關於 php,但它涉及 wordpress,因為我正在建立一個外掛。情況是我有 5 個問題,每個問題有 6 個選擇和一個選擇從每個問題。現在這個人會從每一個或幾個人中選擇任何一個選擇。我已經創造了現在讓我生氣的情況,因為它已經太久了,會做更多的事情,就像將近 100 個組合一樣。我不想要,我知道有一種多維陣列的方式,但不是一個外掛或 php 專家的 wordpress 。所以如果有人可以為我排序。
$qs = $_POST['q1'];
$q2 = $_POST['q2'];
$q3 = $_POST['q3'];
$q4 = $_POST['q4'];
$q5 = $_POST['q5'];
$q6 = $_POST['q6'];
$args = array(
'post_type' => 'product',
'posts_per_page' => -1,
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => 'fashion-follower'
),
// array(
// 'taxonomy' => 'product_cat',
// 'field' => 'slug',
// 'terms' => 'cheap-and-cheerful'
// )
)
);
//The Fashionsia
if (($qs ==='party') && ($q2 === 'clothes') && ($q3 === 'shopping') && ($q5 === 'Sunbathing') && ($q6 === 'mini')){
$query = new WP_Query( $args );
if( $query->have_posts()) : while( $query->have_posts() ) : $query->the_post();
the_post_thumbnail('thumbnail');
endwhile;
endif;
}
//second question loop
$args2 = array(
'post_type' => 'product',
'posts_per_page' => -1,
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => 'the-homemaker'
),
// array(
// 'taxonomy' => 'product_cat',
// 'field' => 'slug',
// 'terms' => 'cheap-and-cheerful'
// )
)
);
//The homemaker
if (($qs ==='drink') && ($q2 === 'candles') && ($q3 === 'house') && ($q4 === 'diy')){
$query = new WP_Query( $args2 );
if( $query->have_posts()) : while( $query->have_posts() ) : $query->the_post();
the_post_thumbnail('thumbnail');
endwhile;
endif;
}
//third loop
$args3 = array(
'post_type' => 'product',
'posts_per_page' => -1,
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => 'entertainment'
),
// array(
// 'taxonomy' => 'product_cat',
// 'field' => 'slug',
// 'terms' => 'cheap-and-cheerful'
// )
)
);
//The Entertainer
if (($qs ==='party-babe') && ($q2 === 'winer')&& ($q4 === 'storm') && ($q6 === 'limo')){
$query = new WP_Query( $args3 );
if( $query->have_posts()) : while( $query->have_posts() ) : $query->the_post();
the_post_thumbnail('thumbnail');
endwhile;
endif;
}
//fourth loop
$args4 = array(
'post_type' => 'product',
'posts_per_page' => -1,
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => 'family-fanatic'
),
// array(
// 'taxonomy' => 'product_cat',
// 'field' => 'slug',
// 'terms' => 'cheap-and-cheerful'
// )
)
);
//The family-fanatic
if (($qs ==='movie') && ($q2 === 'kids')&& ($q6 === 'volvo')){
$query = new WP_Query( $args4 );
if( $query->have_posts()) : while( $query->have_posts() ) : $query->the_post();
the_post_thumbnail('thumbnail');
endwhile;
endif;
}
//fifth loop
//fourth loop
$args4 = array(
'post_type' => 'product',
'posts_per_page' => -1,
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => 'family-fanatic'
),
// array(
// 'taxonomy' => 'product_cat',
// 'field' => 'slug',
// 'terms' => 'cheap-and-cheerful'
// )
)
);
//The romantic
if (($qs ==='Dinner-show') && ($q5 === 'cruiser')){
$query = new WP_Query( $args4 );
if( $query->have_posts()) : while( $query->have_posts() ) : $query->the_post();
the_post_thumbnail('thumbnail');
endwhile;
endif;
}
最佳解決辦法
您的問題不是真的關於 WordPress,它更多的是關於 PHP 和重構。但是我們在這裡看到這麼糟糕的程式碼,下面我將解釋的模式 (MVC) 可以幫助許多其他開發人員,所以我決定寫一個小小的答案。請記住,在我們的網路中有一個專門的網站:Code Review 。不幸的是,很少有 WordPress 開發人員在那裡活躍。
如何重構程式碼
-
刪除無用的程式碼美化休息
-
查詢所有重複表示式並建立例程 (函式或類) 來抽象和封裝這些表示式。
-
分離資料處理,模型 (儲存,獲取,轉換,解釋),從輸出,檢視 (HTML,CSV,任何) 。
1. 刪除無用的程式碼美化休息
輸出
你有這個重複的片段:
if( $query->have_posts()) : while( $query->have_posts() ) : $query->the_post();
the_post_thumbnail('thumbnail');
endwhile;
endif;
每次執行相當昂貴的 the_post()以獲取帖子縮圖。但是這不是必需的,你可以打電話:
echo get_the_post_thumbnail( $post_id, 'post-thumbnail' );
查詢
所以所有你需要的是帖子 ID,這是沒有呼叫 the_post()可用。更好的是:您可以限制查詢以僅獲取 ID 。
一個簡單的例子:
$post_ids = array();
$args = array(
'post_type' => 'post',
'posts_per_page' => 10,
'fields' => 'ids'
);
$query = new WP_Query( $args );
if ( ! empty ( $query->posts ) )
$post_ids = $query->posts; // just the post IDs
現在你有 ID,你可以寫:
foreach ( $post_ids as $post_id )
echo get_the_post_thumbnail( $post_id, 'post-thumbnail' );
沒有開銷,您的程式碼已經更快更容易閱讀。
語法
注意我如何對齊=?這有助於理解程式碼,因為人的心靈專門從事模式識別。支援,我們可以做的很棒的事情。造成混亂,我們卡住了很快。
這也是為什麼我刪除 endwhile 和 endif 的原因。 alternative syntax 是凌亂而難以閱讀的。此外,它使得 working in an IDE 變得更加困難:從表示式的開始到結束,摺疊和跳轉更容易。
預設值
您的 $args 陣列有一些您在任何地方使用的欄位。建立一個預設陣列,然後寫入這些欄位一次:
$args = array(
'post_type' => 'product',
'posts_per_page' => 100,
'fields' => 'ids',
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
)
)
);
再次注意對齊。並注意我如何更改 posts_per_page 值。不要求-1 。當有一百萬個匹配帖子會發生什麼?每次這個查詢執行時,你不想殺死你的資料庫連線,是嗎?誰應該讀這些帖子?始終設定合理的限制。
現在你需要改變的是 $args[ 'tax_query' ][ 'terms' ]。我們稍後會介紹。
2. 查詢所有重複表示式並建立例程
我們已經清理了一些重複程式碼,現在很困難:POST 引數的評估。顯然,由於某些引數,您已經製作了一些標籤。我建議將這些更改名稱更容易理解,但現在我們將使用您的命名方案。
將這些組與其他組分開,建立一個可以分開管理的陣列:
$groups = array(
'fashion-follower' => array(
'q1' => 'party',
'q2' => 'clothes',
'q3' => 'shopping',
'q4' => FALSE,
'q5' => 'sunbathing',
'q6' => 'mini',
),
'the-homemaker' => array(
'q1' => 'drink',
'q2' => 'candles',
'q3' => 'house',
'q4' => 'diy',
'q5' => FALSE,
'q6' => FALSE,
)
);
要填充預設陣列中缺少的 terms 欄位,請執行 $groups 陣列,直到找到匹配項:
function get_query_term( $groups )
{
foreach ( $groups as $term => $values )
{
if ( compare_group_values( $values ) )
return $term;
}
return FALSE;
}
function compare_group_values( $values )
{
foreach ( $values as $key => $value )
{
// Key not sent, but required
if ( empty ( $_POST[ $key ] ) and ! empty ( $value ) )
return FALSE;
// Key sent, but wrong value
if ( ! empty ( $_POST[ $key ] ) and $_POST[ $key ] !== $value )
return FALSE;
}
// all keys matched the required values
return TRUE;
}
我分離了執行透過術語列表和值的比較,因為這是不同的操作。您的程式碼的每一部分都應該只做一件事,你必須保持縮排級別,以提高可讀性。
現在我們有所有的部分,我們把它們粘在一起。
3. 組織:將模型與檢視分開
當我寫模型和觀點時,我有一些想法:MVC 方法。它代表 Model View Controller,一種眾所周知的組織軟體元件的模式。到目前為止,缺點是控制器,我們將看到我們以後如何使用它。
你說,你不太瞭解 PHP,所以我希望你能更多地瞭解輸出。我們從這開始:
class Thumbnail_List
{
protected $source;
public function set_source( Post_Collector_Interface $source )
{
$this->source = $source;
}
public function render()
{
$post_ids = $this->source->get_post_ids();
if ( empty ( $post_ids ) or ! is_array( $post_ids ) )
return print 'Nothing found';
foreach ( $post_ids as $post_id )
echo get_the_post_thumbnail( $post_id, 'post-thumbnail' );
}
}
很簡單:我們有兩種方法:一種用於設定我們的帖子 ID 的源,一種用於渲染縮圖。
你可能會想知道這個 Post_Collector_Interface 是什麼。我們一會兒就到了。
現在來源為我們的看法,模特兒。
class Post_Collector implements Post_Collector_Interface
{
protected $groups = array();
public function set_groups( Array $groups )
{
$this->groups = $groups;
}
public function get_post_ids()
{
$term = $this->get_query_term();
if ( ! $term )
return array();
return $this->query( $term );
}
protected function query( $term )
{
$args = array(
'post_type' => 'product',
'posts_per_page' => 100,
'fields' => 'ids',
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => $term
)
)
);
$query = new WP_Query( $args );
if ( empty ( $query->posts ) )
return array();
return $query->posts;
}
protected function get_query_term()
{
foreach ( $this->groups as $term => $values )
{
if ( compare_group_values( $values ) )
return $term;
}
return FALSE;
}
protected function compare_group_values( $values )
{
foreach ( $values as $key => $value )
{
// Key not sent, but required
if ( empty ( $_POST[ $key ] ) and ! empty ( $value ) )
return FALSE;
// Kent sent, but wrong value
if ( ! empty ( $_POST[ $key ] ) and $_POST[ $key ] !== $value )
return FALSE;
}
// all keys matched the required values
return TRUE;
}
}
這不是那麼微不足道,但是我們已經有了大部分的部分。 protected 方法 (函式) 不能從外部訪問,因為我們只需要它們用於內部邏輯。
public 方法很簡單:首先從上面獲取 $group 陣列,第二個返回一個 Post ID 陣列。再次,我們遇到這個可疑的 Post_Collector_Interface 。
一個 interface is a contract 。它可以由類簽名 (實現) 。需要一個介面,就像我們的類 Thumbnail_List 一樣,意味著:該類期望使用這些公共方法的其他類。
我們來構建那個介面。真的很簡單:
interface Post_Collector_Interface
{
public function set_groups( Array $groups );
public function get_post_ids();
}
嗯,就是這樣。簡單的程式碼,不是嗎?
我們在這裡做了什麼:我們認為 Thumbnail_List 獨立於一個具體的類,而我們仍然可以依靠我們得到的類 $source 的方法。如果稍後改變主意,您可以編寫一個新類來獲取帖子 ID 或使用固定值。只要你實現了介面,檢視就會滿足。您甚至可以使用模擬物件來測試檢視:
class Mock_Post_Collector implements Post_Collector_Interface
{
public function set_groups( Array $groups ) {}
public function get_post_ids()
{
return array ( 1 );
}
}
當您想要測試檢視時,這非常有用。你不想一起測試這兩個具體的類,因為你不會看到錯誤來自哪裡。模擬物件對於錯誤來說太簡單,是單元測試的理想選擇。
現在我們必須把課程結合起來。這是控制器進入舞臺的地方。
class Thumbnail_Controller
{
protected $groups = array(
'fashion-follower' => array(
'q1' => 'party',
'q2' => 'clothes',
'q3' => 'shopping',
'q4' => FALSE,
'q5' => 'sunbathing',
'q6' => 'mini',
),
'the-homemaker' => array(
'q1' => 'drink',
'q2' => 'candles',
'q3' => 'house',
'q4' => 'diy',
'q5' => FALSE,
'q6' => FALSE,
)
);
public function __construct()
{
// not a post request
if ( 'POST' !== $_SERVER[ 'REQUEST_METHOD' ] )
return;
// set up the model
$model = new Post_Collector;
$model->set_groups( $this->groups );
// prepare the view
$view = new Thumbnail_List;
$view->set_source( $model );
// finally render the tumbnails
$view->render();
}
}
控制器是應用程式的一個真正獨特的部分; 模型和檢視可能是 re-used 在這裡和那裡,甚至在完全不同的部分。但控制器存在於這個單一的目的,這就是為什麼我們把 $group 放在這裡。
現在你只需要做一件事:
// Let the dogs out!
new Thumbnail_Controller;
在需要輸出的地方呼叫這一行。
您可以在此 gist on GitHub 中找到此答案的所有程式碼。
參考文獻
注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。