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