динамический выбор таблицы с использованием foreach

#php #mysql #pdo #kohana

#php #mysql #pdo #kohana

Вопрос:

Я использую kohana, и у меня есть эта модель для извлечения результатов поиска из базы данных с использованием PDO:

 class Model_Crud extends Model_Database {

  private $tables=array('articles','comments','pages');

  public function get_search_results()
  {
    $query = DB::query(Database::SELECT, 'SELECT * FROM :table WHERE ( title LIKE :search OR body LIKE :search OR tag LIKE :search)');
    $query->param(':search', $_POST['search'] );
    $query->bind(':table', $table );

    foreach($this->tables as $table)
    {
       //echo $query;
       $result[] = $query->execute();
    }

    return $result;
  }
} 
  

Это не сработает, потому что оператор sql будет выглядеть следующим образом в своей окончательной форме:

 SELECT * FROM 'articles' WHERE ( title LIKE 'a random string' OR body LIKE 'a random string' OR tag LIKE 'a random string')
  

и, естественно, это не удается, поскольку статьи должны быть из '

Можно ли сделать что-то подобное? или мне нужно написать 3 разных запроса, по одному для каждой таблицы?

Ответ №1:

Взглянув на класс Database_Query, не кажется, что то, что вам нужно, можно сделать без создания отдельных запросов для каждой таблицы.

Вы могли бы расширить класс Database_Query set_table методом, который преобразует :table .

Еще лучше, вы могли бы немного абстрагироваться от концепции и добавить новые методы для преобразования параметров, которые не подлежат обработке. Взгляните на Database_Query::compile, чтобы получить представление о том, как это делается. (Это совсем не сложно.)

Комментарии:

1. Я не имел в виду создать абстрактный класс. Я использовал «abstract» как глагол. 🙂

Ответ №2:

Да, просто поместите имя таблицы непосредственно в строку, а не в качестве параметра:

 class Model_Crud extends Model_Database {

  private $tables=array('articles','comments','pages');

  public function get_search_results()
  {
    foreach($this->tables as $table)
    {
       $query = DB::query(Database::SELECT, 'SELECT * FROM ' . $table . ' WHERE ( title LIKE :search OR body LIKE :search OR tag LIKE :search)');
       $query->param(':search', $_POST['search'] );

       //echo $query;
       $result[] = $query->execute();
    }

    return $result;
  }
} 
  

Обычно это не очень хорошая идея из-за внедрения SQL, но поскольку список таблиц закодирован в вашей программе, вам действительно не нужно беспокоиться об этом в данном случае.

Комментарии:

1. именно так я в конечном итоге это и сделал, но я хотел избежать, на случай, если когда-нибудь в будущем я решу выполнить поиск более продвинутым и позволю пользователю выбирать таблицу.. (вы можете представить, как легко было бы забыть экранирование переменной $ table через несколько месяцев):/