问题描述

我的问题是关于 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 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。