Статьи

Простой PHP на основе классов запросов

Хотя обычно рекомендуется использовать какую-то платформу или CMS, иногда проект достаточно мал, так что эти варианты могут отягощать разработку. Однако даже в небольших проектах не следует игнорировать отделение элементов представления от внутренних запросов. Из этого туториала вы узнаете, как создать базовый механизм запросов на основе классов для PHP и MySQL.


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

Нам понадобится новый каталог для хранения всего. В этом случае я назвал это тут . Внутри этого я поместил мои файлы конфигурации в каталог с именем conf . Затем я создам каталог inc (сокращение от include) и помещу в него каталог «class».

Затем внутри / conf мы сделаем config.php . Внутри / inc / class мы сделаем DAL.php . Наконец, в корневом каталоге мы сделаем index.php .

DAL означает «Уровень доступа к данным» или «Связь доступа к данным».

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


Нам нужно создать базу данных и заполнить ее некоторыми данными. Для целей данного руководства это будет просто база данных из двух таблиц с одним отношением «один ко многим». Это просто, чтобы мы могли показать, что наш механизм запросов охватывает хотя бы одно отношение.

Итак, в базе данных с именем «tut» давайте создадим таблицу с именем make и таблицу с именем models . Таблица make будет иметь поля «id» и «name», а таблица моделей будет иметь поля «id», «make» и «name».

Теперь мы можем просто добавить некоторые марки (например, Ford, Chevy и т. Д.) В качестве данных в таблицу марок и некоторые модели, за которые отвечают эти производители.

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


Обычно я не люблю работать с необработанными константами в PHP. Обычно я определяю кучу вещей, а затем создаю некоторые функции для подключения к этим константам. Для этого примера давайте просто упростим и используем константы.

В нашем файле /conf/config.php давайте настроим переменные подключения к нашей базе данных. Пока мы это делаем, давайте добавим include в наш скрипт DAL.php.

01
02
03
04
05
06
07
08
09
10
11
12
<?php
 
// Include DAL
require_once(dirname(dirname(__FILE__)) . ‘/inc/class/DAL.php’);
 
// Database
define ( ‘DB_HOST’, ‘localhost’ );
define ( ‘DB_USER’, ‘root’ );
define ( ‘DB_PASSWORD’, ‘password1’ );
define ( ‘DB_DB’, ‘tut’ );
 
?>

Эта настройка предполагает, что вы используете MySQL через порт по умолчанию.

Теперь внутри /inc/class/DAL.php мы сделаем функцию, которую будем использовать для подключения к нашей базе данных.

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

В случае этого класса мы добавим конструктор, даже если он ничего не должен делать.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
<?php
 
class DAL {
     
  public function __construct(){}
   
  private function dbconnect() {
    $conn = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD)
      or die («<br/>Could not connect to MySQL server»);
         
    mysql_select_db(DB_DB,$conn)
      or die («<br/>Could not select the indicated database»);
     
    return $conn;
  }
   
}
 
?>

Обратите внимание, что область действия метода dbconnect является частной. Это потому, что нам не нужно подключаться к базе данных извне нашего DAL. Вместо этого у нас будут открытые методы запросов, которые будут вызывать dbconnect изнутри DAL. Немного смущает? Не беспокойтесь, читайте дальше.


Чтобы абстрагировать наши запросы, чтобы мы могли повторно использовать короткие фрагменты кода, нам понадобятся две вещи. Во-первых, нам понадобится некоторый класс «обобщенного результата запроса». Во-вторых, нам понадобится общий метод запросов внутри нашего DAL.

Цель всего этого — уметь преобразовывать запросы SQL в объекты и минимизировать использование уродливого цикла while ($ row = mysql_fetch_array ($ result)) . С объектами гораздо проще работать, и мы можем использовать свойства вместо ключей массива.

Короче говоря, мы хотим создать класс, который будет создавать имена свойств на лету и хранить данные, связанные с этими свойствами.

Мы поместим этот класс в наш скрипт /inc/class/DAL.php . Поскольку это новый класс, он будет вне класса DAL.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
class DALQueryResult {
 
  private $_results = array();
 
  public function __construct(){}
 
  public function __set($var,$val){
    $this->_results[$var] = $val;
  }
 
  public function __get($var){
    if (isset($this->_results[$var])){
      return $this->_results[$var];
    }
    else{
      return null;
    }
  }
}

Теперь внутри нашего класса DAL нам нужно создать общий метод запросов, который будет превращать запросы SELECT в объекты DALQueryResult .

По сути, мы хотим превратить каждое возвращаемое имя поля в свойство объекта DALQueryResult .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
private function query($sql){
 
  $this->dbconnect();
 
  $res = mysql_query($sql);
 
  if ($res){
    if (strpos($sql,’SELECT’) === false){
      return true;
    }
  }
  else{
    if (strpos($sql,’SELECT’) === false){
      return false;
    }
    else{
      return null;
    }
  }
 
  $results = array();
 
  while ($row = mysql_fetch_array($res)){
 
    $result = new DALQueryResult();
 
    foreach ($row as $k=>$v){
      $result->$k = $v;
    }
 
    $results[] = $result;
  }
  return $results;
}

Вот частная функция, которая принимает запрос SQL. Он подключается к базе данных и запускает запрос. Затем он проверяет, есть ли какие-либо результаты. Если нет никаких результатов, он возвращает ноль в запросе SELECT , ложь в других запросах. Если запрос был успешным и запрос не был SELECT , он вернет true. Если это был SELECT , то он преобразует результаты в массив объектов DALQueryResult. Это имитирует результаты, которые обычно получают из mysql_query.


Теперь мы готовы написать SQL-запрос. Запросы DAL должны быть очень конкретными как по названию, так и по назначению. Давайте сделаем тот, который найдет все модели данной марки.

Это будет наш первый публичный метод.

1
2
3
4
public function get_models_by_make_name($name){
  $sql = «SELECT models.id as id, models.name as name, makes.name as make FROM models INNER JOIN makes ON models.make=makes.id WHERE makes.name=’$name'»;
  return $this->query($sql);
}

Здесь мы просто пишем запрос и возвращаем результат в виде объектов DALQueryResult. Наш общий метод запроса заботится о делах и принятии решений.

На этом наш скрипт DAL.php закончен. Это должно выглядеть следующим образом.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<?php
 
class DALQueryResult {
     
  private $_results = array();
 
  public function __construct(){}
 
  public function __set($var,$val){
    $this->_results[$var] = $val;
  }
 
  public function __get($var){
    if (isset($this->_results[$var])){
      return $this->_results[$var];
    }
    else{
      return null;
    }
  }
}
 
class DAL {
 
  public function __construct(){}
   
  public function get_models_by_make_name($name){
    $sql = «SELECT models.id as id, models.name as name, makes.name as make FROM models INNER JOIN makes ON models.make=makes.id WHERE makes.name=’$name'»;
    return $this->query($sql);
  }
   
  private function dbconnect() {
    $conn = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD)
        or die («<br/>Could not connect to MySQL server»);
         
    mysql_select_db(DB_DB,$conn)
        or die («<br/>Could not select the indicated database»);
     
    return $conn;
  }
   
  private function query($sql){
 
    $this->dbconnect();
 
    $res = mysql_query($sql);
 
    if ($res){
      if (strpos($sql,’SELECT’) === false){
        return true;
      }
    }
    else{
      if (strpos($sql,’SELECT’) === false){
        return false;
      }
      else{
        return null;
      }
    }
 
    $results = array();
 
    while ($row = mysql_fetch_array($res)){
 
      $result = new DALQueryResult();
 
      foreach ($row as $k=>$v){
        $result->$k = $v;
      }
 
      $results[] = $result;
    }
    return $results;
  }
}
 
?>

Теперь, наконец, перейдем к нашему скрипту /index.php и отобразим наши результаты с помощью DAL. Все, что нам нужно сделать, это включить наш файл /conf/config.php , создать экземпляр DAL и что-то сделать с данными. Вот пример.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
// include configuration
require_once(dirname(__FILE__) . ‘/conf/config.php’);
 
// instanciate a new DAL
$dal = new DAL();
 
// array of makes to check
$makes = array(‘Ford’,’Chevy’,’Honda’);
 
// cycle through the makes
foreach ($makes as $make){
  $results = $dal->get_models_by_make_name($make);
  echo «<h1>Models by $make</h1>»;
   
  // check if there were any results
  if ($results){
    echo «<ul>»;
     
    // cycle through results
    foreach ($results as $model){
        echo «<li>$model->make $model->name (Database ID: $model->id)</li>»;
    }
    echo «</ul>»;
  }
  else{
    // Display a message concerning lack of data
    echo «<p>Sorry, we have no information regarding that manufacturer.</p>»;
  }
}
?>

Как видите, теперь у нас есть результаты, которые мы можем назвать именами полей как свойства объекта PHP.


Часто будет полезно преобразовать универсальный DALQueryResult в более конкретный объект. В этом случае вы можете написать бизнес-объекты, которые принимают DALQueryResult в качестве параметра конструктора. Затем вы просто используете это для создания нового объекта.

Вот пример

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
 
class CarModel{
  private $_id;
  private $_make;
  private $_name;
   
  public function __construct(DALQueryResult $result){
    $this->_id = $result->id;
    $this->_make = $result->make;
    $this->_name = $result->name;
  }
  public function __get($var){
    switch ($var){
      case ‘id’:
        return $this->_id;
        break;
      case ‘make’:
        return $this->_make;
        break;
      case ‘name’:
        return $this->_name;
        break;
      default:
        return null;
        break;
    }
  }
  public function __toString(){
    return $this->_name;
  }
}
 
?>

Затем просто напишите запрос, чтобы вернуть массив этих объектов вместо массива общих объектов DALQueryResult .

Помните, всегда называйте свои запросы очень конкретно.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
public function get_models_by_make_name_as_CarModel($name){
  // Reuse existing query
  $results = $this->get_models_by_make_name($sql);
   
  // check for results
  if (!$results){
    return $results;
  }
  else{
    // array to hold CarModel objects
    $object_results = array();
    // cycle through and convert to CarModel objects
    foreach ($results as $result){
      object_results[] = new CarModel($result);
    }
    // return array of CarModel objects
    return object_results;
  }
}

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


Надеюсь, вам всем понравился урок! Удачи.