問題描述

我的問題是關於 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 開發人員在那裡活躍。


如何重構程式碼

  1. 刪除無用的程式碼美化休息

  2. 查詢所有重複表示式並建立例程 (函式或類) 來抽象和封裝這些表示式。

  3. 分離資料處理,模型 (儲存,獲取,轉換,解釋),從輸出,檢視 (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' );

沒有開銷,您的程式碼已經更快更容易閱讀。

語法

注意我如何對齊=?這有助於理解程式碼,因為人的心靈專門從事模式識別。支援,我們可以做的很棒的事情。造成混亂,我們卡住了很快。

這也是為什麼我刪除 endwhileendif 的原因。 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 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。