สอบถาม " Code OOP PHP " ว่าถูกต้องตามหลักหรือไม่ ? เนื่องจากกำลังศึกษา OOP ครับ
ความจริงแล้วไม่มีหลักการอะไรที่กำหนดได้ตายตัวครับ ขึ้นอยู่กับคนออกแบบ...
ดังนั้นเพื่อให้เป็นไปตามหลัก UML หรือให้เข้าใจได้ตรง เพื่อเข้าใจง่ายขึ้น ก็เลยมีการใช้ความสามารถของหลัก OOP และ UML
ซึ่งมีหลักการอยู่ไม่ว่าจะเป็นคุณสมบัติต่างๆ ไม่ว่าจะเป็น encapsulation, Inheritance, Overload, Override, method type etc...
แต่เท่าที่ดูของคุณยังผิดแปลกไปจากหลักการของ OOP อยู่ พูดไปเด่วยาว...
ตย.ครับ class database ที่ผมในบางงาน (หากไม่ได้ใช้ Framework ) ที่แก้ไขเพื่อให้ดูงายขึ้น
ซึ่งในที่นี้จะไม่รวมเกี่ยวกับ Security หรือการตรวจสอบนะครับ ต้องไปประยุกต์เอา
ผมสร้าง Interface สำหรับ Datbase เพื่อให้รองรับ หลายๆยี่ห้อ และสามารถใช้พร้อมกันได้หลาย Connection ครับ
ซึ่งคุณอาจจะเขียน Driver เพิ่มเข้ามา และใช้งานได้ โดยไม่มีผลกระทบต่อโปรแกรม เพียงเปลี่ยน config อย่างเดียว
หรือหากไม่สะดวกก็ศึกษา PDO ก็ได้
database.php
interface Database {
function connect();
function disconnect();
function tableExists($table);
function getArray($table, $select, $options);
function getObject($table, $select, $options);
function getOneArray($table, $select, $options);
function getOneObject($table, $select, $options);
function delete($table, $options);
function insert($table, $params);
function update($table, $params, $condition);
function debug();
function insert_id();
}
class MySQLii implements Database {
private $sql;
private $db_host;
private $db_user;
private $db_pass;
private $db_name;
private $conn;
function __construct($param = FALSE) {
global $config_db;
$params = $param ? $param : $config_db;
// required $params
$this->db_host = $params['host'];
$this->db_user = $params['user'];
$this->db_pass = $params['pass'];
$this->db_name = $params['db'];
}
public function connect() {
try {
$myconn = mysqli_connect($this->db_host, $this->db_user, $this->db_pass); // or die(mysqli_error());
if ($myconn) {
$seldb = mysqli_select_db($myconn, $this->db_name);
$seldb .= mysqli_query($myconn, "SET NAMES UTF8");
if ($seldb) {
$this->conn = $myconn;
return $myconn;
} else {
return false;
}
} else {
return false;
}
} catch (Exception $e) {
echo $e->getTraceAsString();
}
}
public function debug() {
echo '<pre style="color:red;"><i style="none;">SQL : ', $this->sql;
}
public function disconnect() {
try {
if ($this->conn) {
if (mysqli_close($this->conn)) {
$this->conn = false;
return true;
} else {
return false;
}
}
} catch (Exception $e) {
echo $e->getTraceAsString();
}
}
public function tableExists($table) {
try {
if (!$this->conn)
exit('Error : Connection not found.');
$tablesInDb = mysqli_query($this->conn, "SHOW TABLES FROM " . $this->db_name . " LIKE '" . trim($table) . "'");
if ($tablesInDb) {
if (mysqli_num_rows($tablesInDb) == 1) {
return true;
} else {
echo '<pre>[' . $table . '] not exists</pre>';
return false;
}
} else {
echo '<pre>[' . $table . '] not exists</pre>';
return false;
}
} catch (Exception $e) {
echo $e->getTraceAsString();
}
}
public function getArray($table, $select = FALSE, $options = FALSE) {
if (!self::tableExists($table)) {
return FALSE;
} else {
$sql = 'SELECT ' . ($select ? ' ' . $select : '*') . ' FROM ' . $table . ($options ? ' ' . $options : NULL);
$this->sql = $sql;
$q = mysqli_query($this->conn, $sql);
if (!$q)
return 'Error : ' . $sql;
$data = FALSE;
while ($row = mysqli_fetch_array($q)) {
$data[] = $row;
}
return $data;
}
}
public function getObject($table, $select = FALSE, $options = FALSE) {
if (!self::tableExists($table)) {
return FALSE;
} else {
$sql = 'SELECT ' . ($select ? ' ' . $select : '*') . ' FROM ' . $table . ($options ? ' ' . $options : NULL);
$this->sql = $sql;
$q = mysqli_query($this->conn, $sql);
if (!$q)
return 'Error : ' . $sql;
$data = FALSE;
while ($row = mysqli_fetch_object($q)) {
$data[] = $row;
}
return $data;
}
}
public function getOneArray($table, $select = FALSE, $options = FALSE) {
if (!self::tableExists($table)) {
return FALSE;
} else {
$sql = 'SELECT ' . ($select ? ' ' . $select : '*') . ' FROM ' . $table . ($options ? ' ' . $options : NULL);
$this->sql = $sql;
$q = mysqli_query($this->conn, $sql);
if (!$q)
return 'Error : ' . $sql;
$data = mysqli_fetch_assoc($q);
unset($data['password']);
return $data;
}
}
public function getOneObject($table, $select = FALSE, $options = FALSE) {
if (!self::tableExists($table)) {
return FALSE;
} else {
$sql = 'SELECT ' . ($select ? ' ' . $select : '*') . ' FROM ' . $table . ($options ? ' ' . $options : NULL);
$this->sql = $sql;
$q = mysqli_query($this->conn, $sql);
if (!$q)
return 'Error : ' . $sql;
$data = mysqli_fetch_object($q);
return $data;
}
}
public function delete($table, $options) {
if (!self::tableExists($table)) {
return FALSE;
} else {
$sql = 'DELETE FROM ' . $table . ' FROM ' . $table . ' WHERE ' . $options;
$this->sql = $sql;
$q = mysqli_query($this->conn, $sql);
if (!$q)
return 'Error : ' . $sql;
else
return TRUE;
}
}
public function insert_id() {
return mysqli_insert_id($this->conn);
}
public function insert($table, $params = array()) {
if (!self::tableExists($table)) {
return FALSE;
} else {
$sql = 'INSERT INTO ' . $table;
$this->sql = $sql;
var_dump($params);
if (!is_array($params))
return 'Required paramse(array) -> ' . $params;
foreach ($params as $key => $value) {
$keys[] = $key;
$val[] = is_string($value) ? ('"' . $value . '"') : $value;
}
$sql .= ' (' . implode(',', $keys) . ') VALUES (' . implode(',', $val) . ')';
$this->sql = $sql;
$q = mysqli_query($this->conn, $sql);
if (!$q)
return FALSE;
else
return mysqli_insert_id($this->conn);
}
}
public function update($table, $params = array(), $condition) {
if (!self::tableExists($table)) {
return FALSE;
} else {
$sql = 'UPDATE ' . $table;
$this->sql = $sql;
if (!is_array($params))
return '<pre style="color:red;">Required params(array) -> ' . $params . '</pre>';
foreach ($params as $key => $value) {
$cols_val[] = $key . '=' . (is_string($value) ? ('"' . $value . '"') : $value);
}
$sql .= ' SET ' . implode(',', $cols_val) . ' WHERE ' . $condition;
$this->sql = $sql;
$q = mysqli_query($this->conn, $sql);
if (!$q)
return FALSE;
else
return TRUE;
}
}
}
class GetDriver {
public $driver = NULL;
function __construct($config_db) {
if (!self::checkParamitors($config_db)) {
print 'Check your : $config_db';
return FALSE;
}
$this->driver = $config_db['driver'];
}
private function checkParamitors($params = array()) {
// check $params here...
return 'something';
}
}
จากนั้น สร้างไฟล์ congfig เพื่อเก็บค่า congfig ต่างๆไว้
config.php
$config_db = array(
'host' => '?',
'user' => '?',
'pass' => '?',
'db' => '?',
'driver' => 'MySQLii'
);
$config_db2 = array(
'host' => '?-2',
'user' => '?-2',
'pass' => '?-2',
'db' => '?-2',
'driver' => 'MySQLii'
);
ตัวอย่างผู้ใช้งาน
users.php
class User {
// parent class ซึ่ง user ทุกคนมี
protected $db;
function __construct() {
//---------- User database
global $config_db;
$driver = new GetDriver($config_db);
$db = $driver->driver;
$this->db = new $db();
$this->db->connect();
}
function login() {
// login here...
}
function everyUser() {
// ???...
}
}
class Guest extends User {
// child class
function guestTodo() {
var_dump('Show SQL : ' . $this->db->debug());
echo 'todo';
}
}
interface UserSystem {
// กำหนดว่า User ที่ login เข้ามาจะต้องมีเหมือนกัน
function logout(); // ซึ่ง user แต่ละระดับ อาจล็อก logout ต่างกันด้วยระบบ ความปลอดภัยในแต่ละระดับ การใช้งานหน้อจอ
function userCandoNotSame(); // ความสามารถที่ทำได้ อาจจะต่างกัน
}
class UserAdmin extends User implements UserSystem {
// child class ความสามารถต่างๆของ Admin
protected $db2;
function __construct() {
//---------- Admin ใช้ 2 Database เพื่อบางอย่าง
global $config_db2;
$driver = new GetDriver($config_db2);
$db = $driver->driver;
$this->db2 = new $db($config_db2);
$this->db2->connect();
}
function logout() {
var_dump($this->db);
return 'adminLogout';
}
function userCandoNotSame() {
echo 'Conection 2 : ';
var_dump($this->db2);
return 'adminCando';
}
function adminWork() {
return 'work for admin';
}
}
class Member extends User implements UserSystem {
// child class ความสามารถต่างๆของ Member
function logout() {
var_dump($this->db);
return 'userLogout';
}
function userCandoNotSame() {
return 'memberCando';
}
function memberSomthing() {
return 'member *0*';
}
}
$g = new Guest();
$g->guestTodo();
echo '<hr/>';
$a = new UserAdmin();
echo $a->userCandoNotSame();
echo '<hr/>';
$m = new Member();
echo $m->userCandoNotSame();
echo '<hr/>';
ประวัติการแก้ไข 2013-04-05 00:27:01 2013-04-05 00:32:35 2013-04-05 00:38:47 2013-04-05 00:39:58
Date :
2013-04-05 00:23:36
By :
t-monroe
ขอบคุณ T-MONROE มากๆครับ
มีตัวอย่างมาให้ศึกษา และเป็นแนวทางในการเขียน
ขอบคุณอีกครั้งครับ : )
Date :
2013-04-05 08:04:03
By :
blackedition
ผมใช้ php 5.4 นะ แต่ยังไง oop ของ php ก็ยังไม่ค่อยจะสมบูรณ์เท่าไหร่
ที่มีใช้อยู่ก็ทำมาแบบแก้ขัดให้เหมือนมี อย่าง properties, overload method, enum
หรืออีกหลายๆ อย่างพวกนี้ (php มีแค่ function (method)) มันก็สามารถทำได้
แต่อย่างที่บอกแหละว่าทำไว้แบบแก้ขัดให้มี เวลาใช้ ide
มันเลยไม่มี autocomplete หรือ autosuggest ให้ ถ้าเคยใช้แบบมีตัวช่วยมาก่อน
ก็เขียนช้าลงนิดหน่อย แต่ถ้าไม่ได้ใช้ตรงนี้ก็คงเฉยๆ
แต่แนะนำว่าถ้าจะ oop สุดๆ ลอง java หรือ jsp ดู เขียนไม่ยากอย่างที่คิด
แต่ยากตรง config เพราะทำอะไรก็ต้อง config เบื่อตรงนี้แหละ
หรือถ้าไม่อยากยุ่งยากก็ลอง .net ดู next next next จบ แล้วก็โค้ดอย่างเดียวพอ
Date :
2013-04-05 09:49:23
By :
ห้ามตอบเกินวันละ 2 กระทู้
ลืมบอกไป ใน php 5.4 มันมี namesapce ให้ใช้แล้วนะ หรือมีตั้งแต่ 5.3 แล้วก็ไม่รู้ พอดีเพิ่งมาจับ php
เลยไม่รู้ว่ามัน update ตังแต่ version ไหน มาถึงก็จับ 5.4 เลย
namesapce เอาไว้สำหรับจัดกลุ่ม class แล้วก็มีประโยช์อีกอย่างคือทำ autoload จะไม่ได้ต้องมา include file เยอะๆ
เวลามีหลายๆ class
Date :
2013-04-05 09:54:50
By :
ห้ามตอบเกินวันละ 2 กระทู้
ตัวอย่างการใช้งาน oop ของ php นะ แต่ในโลกของ oop ไม่ใช่แค่นี้
index.php
<?php
require_once (dirname(__FILE__) . '/database/include.php');
// autoload
spl_autoload_extensions(".php");
spl_autoload_register();
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>PHP OOP</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
</head>
<body>
<form id="form1" name="form1" method="post">
<header>
Header
</header>
<nav>
<?php
$sqlsvr = new database\sql_server();
$conn = $sqlsvr -> open_connection();
$query1 = "SELECT ID, SectionCode, SectionName FROM Section WHERE ID BETWEEN ? AND ? OR ID = ? OR SectionName = ?";
$params1 = array(2, 5, 7, "OPD");
$result1 = $sqlsvr -> execute_query($conn, $query1, $params1);
if ($result1)
{
$i = 0;
$len = count($result1);
foreach ($result1 as $r)
{
echo "<a href=\"$r->SectionCode\">$r->SectionName</a>";
if ($i != $len - 1)
{
echo " | ";
}
$i++;
}
}
$sqlsvr -> close_connection($conn);
?>
</nav>
<aside>
ASide
</aside>
<article>
<section>
<?php
$conn = $sqlsvr -> open_connection();
$query2 = "SELECT ID, MinistryName FROM Ministry";
$result2 = $sqlsvr -> execute_query($conn, $query2);
if ($result2)
{
echo "<ul>";
foreach ($result2 as $r)
{
echo "<li>$r->ID $r->MinistryName</li>";
}
echo "</ul>";
}
$sqlsvr -> close_connection($conn);
?>
</section>
</article>
<footer>
Footer
</footer>
</form>
</body>
</html>
ส่วนพวกนี้วางไว้ใน folder database เพราะเป็น class ใน namespace ชื่อ database
ถ้าเอาไว้ไม่ถูกที่จะใช้ autoload ไม่ได้
include.php
<?php
// Database
define('DB_HOST', 'localhost\sqlexpress');
define('DB_NAME', 'SqlServer2008');
define('DB_USER', '');
define('DB_PASSWORD', '');
define('DB_CHARACTERSET', 'UTF-8');
?>
idatabase.php
<?php
namespace database
{
interface idatabase
{
public function open_connection();
public function close_connection($conn);
public function execute_nonquery($conn, $query, $params);
public function execute_query($conn, $query, $params );
public function begin_transaction($conn);
public function commit_transaction($conn, $querys);
}
}
?>
sql_server.php
<?php
namespace database
{
class sql_server implements idatabase
{
public function open_connection()
{
$connection_info = array("UID" => DB_USER,
"PWD" => DB_PASSWORD,
"Database" => DB_NAME,
"CharacterSet" => DB_CHARACTERSET);
$conn = sqlsrv_connect(DB_HOST, $connection_info);
if ($conn === FALSE)
{
echo "Unable to connect.<br />";
die(print_r(sqlsrv_errors(), TRUE));
}
return $conn;
}
public function close_connection($conn)
{
sqlsrv_close($conn);
}
public function execute_nonquery($conn, $query, $params = FALSE)
{
$resource = ($params === FALSE) ? sqlsrv_query($conn, $query) : sqlsrv_query($conn, $query, $params);
if ($resource === FALSE)
{
echo "Error in executing query.<br />";
die(print_r(sqlsrv_errors(), TRUE));
}
return $resource;
}
public function execute_query($conn, $query, $params = FALSE)
{
$resource = ($params === FALSE) ? sqlsrv_query($conn, $query) : sqlsrv_query($conn, $query, $params);
if ($resource === FALSE)
{
echo "Error in executing query.<br />";
die(print_r(sqlsrv_errors(), TRUE));
}
$results = array();
while ($row = sqlsrv_fetch_array($resource))
{
$result = new query_result();
foreach ($row as $key => $value)
{
$result->$key = $value;
}
$results[] = $result;
}
return $results;
}
public function begin_transaction($conn)
{
if (sqlsrv_begin_transaction($conn) === FALSE )
{
echo "Cann't begin transaction.<br />";
die(print_r( sqlsrv_errors(), TRUE));
}
}
public function commit_transaction($conn, $querys)
{
$result = is_array($querys);
if ($result === TRUE)
{
foreach ($querys as $q)
{
$result = $result && $q;
}
if ($result === TRUE)
{
sqlsrv_commit($conn);
}
else
{
sqlsrv_rollback($conn);
}
}
return $result;
}
}
}
?>
query_result.php
<?php
namespace database
{
class query_result
{
private $_results = array();
public function __set($key, $value)
{
$this->_results[$key] = $value;
}
public function __get($key)
{
if (isset($this->_results[$key]))
{
return $this->_results[$key];
}
else
{
return null;
}
}
}
}
?>
วิธีการสร้าง enum
ienum.php
<?php
namespace base
{
interface ienum
{
/**
* Return an array containing the enum values to iterate over
* @return Traversable Contains enum values
*/
public static function values();
}
}
?>
direction.php
<?php
namespace enum
{
spl_autoload_extensions(".php");
spl_autoload_register();
use base\ienum as ienum;
abstract class direction implements ienum
{
const Up = 'up';
const Down = 'down';
const Left = 'left';
const Right = 'right';
public static function values()
{
return new ArrayIterator(array(direction::Up,
direction::Down,
direction::Left,
direction::Right));
}
}
}
?>
ใช้งาน enum
Code (PHP)
spl_autoload_extensions('.php');
spl_autoload_register();
use jquery\ui\enum as enum;
$up = enum\direction::Up;
Date :
2013-04-05 12:16:29
By :
ห้ามตอบเกินวันละ 2 กระทู้
Load balance : Server 01