如何简化与preg_match一起使用的开关盒?

时间:2014-03-01 04:34:46

标签: php

我有一串格式:

$search_cases = $variable1.'*'.$variable2.'*'.$variable3.'*'.$variable4;

其中所有变量可以是字符串'no'或数值(整数)。我想涵盖所有可能的变化。我发现使用switch case(而不是if..elseif..)的唯一可行方式。所以我的代码现在看起来像这样:

switch($search_cases) {
    case (preg_match("/no.no.no.no/", $search_cases) ? $search_cases : !$search_cases): echo 'no filter <br />'; break;
    case (preg_match("/(\d+).no.no.no/", $search_cases) ? $search_cases : !$search_cases): echo 'filters used: location<br />'; break;
    case (preg_match("/no.(\d+).no.no/", $search_cases) ? $search_cases : !$search_cases): echo 'filters used: event<br />'; break;
    case (preg_match("/no.no.(\d+).no/", $search_cases) ? $search_cases : !$search_cases): echo 'filters used: artist<br />'; break;
    case (preg_match("/no.no.no.(\d+)/", $search_cases) ? $search_cases : !$search_cases): echo 'filters used: priceinterval<br />'; break;
    case (preg_match("/(\d+).(\d+).no.no/", $search_cases) ? $search_cases : !$search_cases): echo 'filters used: location event<br />'; break;
    case (preg_match("/no.(\d+).(\d+).no/", $search_cases) ? $search_cases : !$search_cases): echo 'filters used: event artist<br />'; break;
    case (preg_match("/no.no.(\d+).(\d+)/", $search_cases) ? $search_cases : !$search_cases): echo 'filters used: artist priceinterval<br />'; break;
    case (preg_match("/(\d+).no.no.(\d+)/", $search_cases) ? $search_cases : !$search_cases): echo 'filters used: location priceinterval<br />'; break;
    case (preg_match("/(\d+).(\d+).(\d+).no/", $search_cases) ? $search_cases : !$search_cases): echo 'filters used: location event artist<br />'; break;
    case (preg_match("/no.(\d+).(\d+).(\d+)/", $search_cases) ? $search_cases : !$search_cases): echo 'filters used: event artist priceinterval<br />'; break;
    case (preg_match("/(\d+).no.(\d+).(\d+)/", $search_cases) ? $search_cases : !$search_cases): echo 'filters used: location artist priceinterval<br />'; break;
    case (preg_match("/(\d+).(\d+).no.(\d+)/", $search_cases) ? $search_cases : !$search_cases): echo 'filters used: location event priceinterval<br />'; break;
    case (preg_match("/(\d+).(\d+).(\d+).(\d+)/", $search_cases) ? $search_cases : !$search_cases): echo 'filters used: location event artist priceinterval<br />'; break;
}

当然,我不需要回显过滤器,而是需要在不同的表中进行各种查询。

我基本上试图完成的是我在页面上有4个过滤器(下拉列表 - 彼此独立),我尝试根据选定的过滤器获得结果。这些信息分散在几个关系表中。

所以我的问题是:是否有更简单的方法来涵盖不同的情况,或者还有其他一些最佳实践来实现相同的结果?感谢。

修改

我需要从3个表中提取数据:

表:事件

table event

表:艺术家

table artist

表:price_interval

table price_interval

表:ticket_price

table ticket_price

还有其他表,例如位置(从事件表中提取基于location_id的名称,以及ticket_type和ticket_price(都与事件表相关),但与我猜的问题无关。 / p>

过滤器包括:位置/事件/艺术家/价格区间。

我需要的结果基于这些,所以如果我选择一个位置(保持其他过滤器不变 - 变量没有没有没有案例),该页面将返回该位置的所有事件。如果我之后选择了一个艺术家(变量没有变量没有案例),那么页面会显示所有位置和艺术家马赫的事件。希望现在更清楚了。

EDIT2

更改回声以反映不同的情况。对于每种情况,我都需要不同的结果。

1 个答案:

答案 0 :(得分:1)

这肯定是可以解决的,没有任何正则表达式的参与,你应该只提交四个过滤器作为单独的输入变量而不是这个怪物,然后为每个过滤器构建所需的查询/条件。

我实际上没有针对实际的数据库测试此代码。

<!--
HTML for the form
  if the user hasn't selected any value, just use a blank value 
  instead of a magic string "no"
-->

<form>
    <select name="filters[location]">
        <option value=""> - Select location - </option>
        <option value="1">Location 1</option>
        ....
    </select>
    ..other filters..
</form>

// PHP code to process search

$query = 'SELECT ev.* FROM event ev';

$joins = array();

$conditions = array();

$params = array();

if(!empty($_POST['filters']['location'])) {
    $location = $_POST['filters']['location'];
    $conditions []= 'ev.location_id = :location_id';
    $params[':location_id'] = $location;
}

if(!empty($_POST['filters']['artist'])) {
    $artist = $_POST['filters']['artist'];
    $joins []= 'INNER JOIN artist a ON a.event_id = ev.id';
    $conditions []= 'a.id = :artist_id';
    $params[':artist_id'] = $artist;
}

// since you haven't explained what the "event" filter does, I'm taking a wild guess - adjust if needed
if(!empty($_POST['filters']['event'])) {
    $event = $_POST['filters']['event'];
    $conditions []= 'ev.category_id = :cat_id OR ev.sub_category_id = :sub_cat_id';
    $params [':cat_id'] = $event;
    $params [':sub_cat_id'] = $event;
}

// it's not entirely clear to me how the tables involved in this filter connect with each other - adjust if needed
if(!empty($_POST['filters']['price'])) {
    $price = $_POST['filters']['price'];

    // load the price interval somehow
    $price_interval = getPriceInterval($price);

    $joins []= 'INNER JOIN ( SELECT DISTINCT event_id FROM ticket_price tp WHERE tp.price BETWEEN :minPrice AND :maxPrice ) p ON p.event_id = ev.id';
    $conditions [':minPrice'] = $price_interval['minval'];
    $conditions [':maxPrice'] = $price_interval['maxval'];
}

if(count($joins)) {
    $query .= ' ' . implode(' ', $joins);
}

if(count($conditions)) {
    foreach($conditions as $ix => $condition) {
        $conditions[$ix] = '(' . $condition . ')';
    }
    $query .= ' WHERE ' . implode(' AND ', $conditions);
}

// you can dump the query here to see the final SQL and parameters
// var_dump($query, $params);

// here I'm assuming you're using PDO for DB access
$finder = $db->prepare($query);
$finder->execute($params);

$events = $finder->fetchAll(PDO::FETCH_ASSOC);

旁注:您需要了解MySQL列声明255int(255)的实际含义。