2015-11-30 2 views
0

Я пришел из мира процедурного программирования, когда ассемблер стал моим первым языком, а PL/1 и Cobol были языками, с которых я узнал большинство моих (плохих) привычек.Структура ООП для старого процедурного программиста

Это мой первый пост здесь, поэтому, пожалуйста, примите мои извинения, если я не делаю это на 100% правильно.

Я переписываю наши интерфейсные и бэкэнд-системы от процедурного php к ООП, и я не совсем понимаю, какую структуру использовать.

В старой системе у нас есть несколько скриптов, которые включают в себя xxx.inc.php с используемыми функциями, и те xxx.inc.php, в свою очередь, включают в себя другие xxx.inc.php, такие как db.inc.php, api_pj.inc.php и т. д.

Попытка сделать это ООП, я создаю один файл для каждого класса и автоматически загружаю их, но я не могу понять, как обращаться с общими классами (база данных, подключение к внешним api и т. д.). При тестировании я использовал наследование, и он отлично работает, но он очень странный. Я не вижу, чтобы класс клиента был дочерним классом базы данных. Также я не понимаю, что нужно определить, а не. Должны ли быть определены все переменные в классах?

Приведенный ниже пример не работает, поскольку соединение с базой данных недоступно для класса Customer. Когда «клиент класса расширяет базу данных», все работает нормально, но я полагаю, что есть более правильный способ сделать это?

Отредактированный код ниже после ответа от Alex Андрей

the_example_page.php

// autoloader 
spl_autoload_register(function ($class) { 
    require_once 'classes/' . $class . '.class.php'; 
}); 

// data for testing 
$customer_id = '12090'; 
$order_id = '31480'; 

// db 
$db = new DB(); 
$db_conn = $db->db_connect(); 

// get customer name data and print it: 
$customer = new Customer($db_conn); 
$customer_data = $customer->get_customer_info($customer_id); 
print $customer_data['name']; 

// get order date and print it: 
$order = new Order($db_conn); 
$order_data = $order->get_order_info($order_id); 
print $order_data['date']; 

DB.class.php

class DB 
{ 
    public function __construct() {} 

    public function db_connect() 
    { 
     static $db_conn; 

     if(!$db_conn) 
     { 
      $db_conn = pg_connect("dbname=database user=user password=PaSsWoRd"); 
     } 
     return $db_conn; 
    } 

    public function db_exec($sql) 
    { 
     if(!$sql) return; 
     $db_conn = $this->db_connect(); 
     $result = @pg_exec($db_conn,$sql); 
     if(!$result) 
     { 
      return; 
     } 
     $ret[result] = $result; 
     return $ret; 
    } 

    public function db_getrow(&$a) 
    { 
    # a bunch of stuff in real function, but here only a plain fetch_array as example  
     $ret = pg_fetch_array($a); 
     return $ret; 
    } 
} 

Customer.class.php

class Customer 
private $conn; 
{ 
public function __construct($db) 
{ 
    $this->conn=$db; 
} 

    public function get_customer_info($customer_id) 
    { 
     return $this->conn->db_getrow($this->conn->db_exec("SELECT * FROM customer WHERE customerid = $customer_id;")); 
    } 

    public function get_all_customers($status) 
    { 
     return $this->conn->db_exec("SELECT * FROM customer WHERE status = $status;"); 
    } 
} 

Order.class.php

class Order 
{ 
private $conn; 
{ 
public function __construct($db) 
{ 
    $this->conn=$db; 
} 

    public function get_order_info($order_id) 
    { 
     return $this->conn->db_getrow($this->conn->db_exec("SELECT * FROM order WHERE orderid = $order_id;")); 
    } 

    public function get_all_orders($status) 
    { 
     return $this->conn->db_exec("SELECT * FROM order WHERE status = $status;"); 
    } 
} 
+2

Действительно, Cus tomer * не является * базой данных, поэтому он не должен наследовать его. Взгляните на *** зависимую инъекцию ***. Со стороны потребителя, которая выглядит как '$ db = новая база данных ('foo', 'bar'); $ cust = новый клиент ($ db); '. Еще лучше: '$ manager = new CustomerManager ($ db); $ cust = $ manager-> get (42); '. Посмотрите на шаблон * хранилища. * – deceze

ответ

1

UPDATE
Расширенного пример о том, как изменить класс подключения к БД и класс Order

база данных класса

class DB 
{ 
    private $conn; 
    private $user; 
    private $password; 
    private $database; 

    public function __construct($database,$username,$password){ 

     $this->user = $user; 
     $this->password = $password; 
     $this->database = $database; 

    } 

    public function connect(){ 
     if(!$this->conn){ 
      $this->conn = pg_connect("dbname=$this->database user=$this->user password=$this->password"); 
     } 
     return $this->conn; 
    } 

    public function db_exec($sql){ 
     if(!$sql) return; // add some relevant error message 

     if (!$this->conn){ 
      $this->connect(); 
     } 

     $result = pg_exec($this->conn,$sql); 

     if(!$result){ 
      return; 
     } 
     $ret[result] = $result; 

     return $ret; 
    } 

    public function db_getrow(&$a){ 
    # a bunch of stuff in real function, but here only a plain fetch_array as example  
     $ret = pg_fetch_array($a); 
     return $ret; 
    } 
} 

Заказать класс

class Order 
{ 
    private $dbObj; 

    public function __construct($db) 
    { 
     $this->dbObj=$db; 
    } 

    public function get_order_info($order_id) 
    { 
     $result = $this->dbObj->db_exec("SELECT * FROM order WHERE orderid = $order_id;"); 
     return $this->dbObj->db_getrow($result); 
    } 

    public function get_all_orders($status) 
    { 
     return $this->conn->db_exec("SELECT * FROM order WHERE status = $status;"); 
    } 
} 

Использование

$db = new DB("myDatabase","user","password"); 
$db->connect(); 

$order = new Order($db); 

Вы не должны extend все, только то, что имеет смысл.

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

Ex.

$customer = new Customer($db); 
$order = new Order($db); 

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

class Customer{ 
    private $conn; 

    // ... 
} 

и конструктор будет выглядеть следующим образом

public function __construct($db) { 
    $this->conn = $db; 
} 

использовать его в методах, таких как так

public function get_order_info($order_id){ 
    return $this->conn->db_getrow($this->db_exec("SELECT * FROM order WHERE orderid = $order_id;")); 
} 
+0

Спасибо за ответ. Поэтому, если я правильно вас понимаю, я спрошу (если это так называется) базу данных в файле_example_page.php через $ db = new DB(); и отправить это другим классам? Но это объект, а не соединение? Или? В DB.class.php соединение - это $ db_conn, поэтому я подумал, что это будет то, что должно быть передано другим классам. (Наверное, я все это не понимаю, но прочитаю через него больше, когда вернусь через час) –

+0

Да. Довольно много. Объект DB имеет метод, который возвращает «соединение». Вы передадите это как аргумент для других классов. Это «экземпляр» :) –

+0

Я обновил код, но получаю ошибку: PHP Неустранимая ошибка: вызов функции-члена db_getrow() для не-объекта в классах/Customer.class.php on line 12 Строка 12: return $ this-> conn-> db_getrow ($ this-> conn-> db_exec ("SELECT * FROM customer WHERE customerid = $ customer_id;")); –

-1

Вы можете extend другие классы, если они используют database класс, а затем вызывать их в детском конструкторе. Следите за конфликтующими переменными в рамках методов, если вы выберете этот подход.

Если Customer класса расширяет Database класса, то он будет иметь доступ к методам Database и т.д.

class Database{ 
    public function __construct(){ 
    } 
    /* other methods*/ 
} 

class Customer extends Database{ 
    public function __construct(){ 
     parent::__construct(); 
    } 
} 
class Order extends Database{ 
    public function __construct(){ 
     parent::__construct(); 
    } 
} 
+0

спасибо за нисходящее так быстро проклятье ... случайно отправьте половину готового сообщения и ... – RamRaider

+0

Речь идет не о полузаготовленном ответе, а о плохих методах ООП. Клиент * не * база данных, поэтому не должен наследовать его. См. Мой комментарий по вопросу. – deceze

+0

Во-вторых, если ваш клиент ничего не делает в своем конструкторе, кроме вызова родительского конструктора, просто оставьте его полностью, нет необходимости писать его вообще. – deceze

Смежные вопросы