Öne Çıkanlar
PHP ile Web Programcılığı
|
Her Yönüyle PHP 6
|
MySQL ve PostgreSQL ile Veritabanı Programlama
|
Uzmanlar İçin PHP 5
|
Anket
db class
Bir framework'dur gidiyor. Herkes bir framework kullanıyor. Yapılarını hiç incelemeden herkes kafasına yatan bir framework'ü kullanıyor ama hiçkimse bu framework'lerin performansları hakkında bir düşünceleri yok.Açıp içerisini incelediğimizde basit işlemler için onlarca işlem yapan bir framework'den performans beklemek bana göre saçma. Framework kullanan developerlar kendini geliştirme konusunda geri kaldığını belirtmek isterim.
Bu bağlamda kitaplarımda da vermiş olduğum db class örneğini burada da vermek istiyorum. Öncelikle db class için interface arayüzünü vererek konuya başlayalım.
<?php
interface dbInterface{
/**
* slect methodu
*
* @param object $res
* @param string $query
* @param array $dataArr
* @param boolean $trigger
*/
public function select(&$res, $query, $dataArr = array(), $trigger = true);
/**
* insert metodu
*
* @param string $query
* @param array $dataArr
* @param boolean $trigger
*/
public function insert($query, $dataArr = array(), $trigger = true);
/**
* update metodu
*
* @param string $query
* @param array $dataArr
* @param boolean $trigger
*/
public function update($query, $dataArr = array(), $trigger = true);
/**
* delete metodu
*
* @param string $query
* @param array $dataArr
* @param boolean $trigger
*/
public function delete($query, $dataArr = array(), $trigger = true);
/**
* transaction başlatır
*
* @param boolean $autocommit
*/
public function startTransaction($autocommit = false);
/**
* commit metodu
*
*/
public function commit();
/**
* rollback metodu
*
*/
public function rollback();
/**
* en son kayıt id si
*
*/
public function last_Id();
}
?>
Burada db class içerisinde kullanmak zorunda olduğumuz methodları tanımlayan interface'imizi belirttikten sonra, db class'ımızı tanımlayabiliriz. Aşağıdaki class'da temel olarak select, insert, update ve delete dört ana methodu bulunmaktadır. Burada verdiğimiz db class tüm database işlemlerini yürütür. MySQLi kütüphanesinin prepare yapısı kullanıldığından, SQL Injection konusunda herhangi bir sıkıntı çekmeden projelerinizi oluşturabilirsiniz.
<?php
class db implements dbInterface
{
/**
* Kaç satırda işlem yaptığını return eder
*
* @var integer
*/
public $affected_rows;
/**
* MySQL'e yapılan bağlantı sabiti
*
* @var obje
*/
public $mysqli;
/**
* debug ekranı
*
* @var boolean
*/
public $debug = false;
/**
* state alanı
*
* @var boolean
*/
protected $db_state = true;
/**
* error_no
*
* @var integer
*/
protected $current_err_no;
/**
* bağlantı durumu
*
* @var boolean
*/
private $connection;
/**
* stmt object
*
* @var object
*/
private $stmt;
/**
* class'ın construct'ı
*
* @param string $host
* @param integer $port
* @param string $user
* @param string $pass
* @param string $db
* @param string $character
*/
public function __construct() {
try {
$this->mysqli = new mysqli ( db_host, db_user, db_pass, db_dbName, db_port );
$this->mysqli->set_charset ( db_character );
$this->connection = true;
$this->db_state = true;
} catch ( Exception $error ) {
$this->connection = false;
$this->db_state = false;
$this->current_err_no = 2;
trigger_error ( $error->getMessage (), E_USER_WARNING );
}
}
/**
* Array'ı boşaltan method
*
* @param boolean $resource
* @return boolean
*/
public function empty_results(&$resource) {
if ($resource != null) {
try {
if (isset ( $resource->dataArr ) && is_array ( $resource->dataArr ))
array_splice ( $resource->dataArr, 0, $resource->num_rows );
$resource->num_rows = 0;
$resource->dataArr = null;
$resource->dataArr = array ();
$this->affected_rows = 0;
unset ( $resource );
return true;
} catch ( Exception $error ) {
trigger_error ( $error->getMessage (), E_USER_NOTICE );
return false;
}
}
return false;
}
/**
* Data tipini belirler
*
* @param string|integer|double|blob $data
* @return string s|i|d|b
*/
private function getDataType($data) {
if (is_string ( $data ))
$type = 's';
elseif (is_integer ( $data ))
$type = 'i';
elseif (is_double ( $data ))
$type = 'd';
else
$type = 'b';
return $type;
}
/**
* dataSet'ini belirleyen method
*
* @param Array $dataArr
* @return array|boolean
*/
private function setDataType($dataArr) {
if (is_array ( $dataArr )) {
$count = count ( $dataArr );
$dataType = $data = '';
for($i = 0; $i < $count; $i ++) {
$dataType .= self::getDataType ( $dataArr [$i] );
$data .= '$dataArr[' . $i . '],';
}
return array ($dataType, self::setComma ( $data ) );
} else {
trigger_error ( 'Array değil', E_USER_ERROR );
return false;
}
}
/**
* query işlemini yapan method.
* Sadece db.class içerisinden çağrılabilir.
*
* @param string $query
* @param boolean $trigger
* @param boolean $use_result "select'lerde MYSQLI_USE_RESULT ekler"
* @return boolean
*/
protected function &execute($query, $trigger, $use_result = false) {
try {
if ($trigger == false) {
if ($use_result)
if (! $result = & $this->mysqli->query ( $this->mysqli, $query, MYSQLI_USE_RESULT ))
{
throw new Exception ( "<b><br>$query<br></b>" );
}
else if (! $result = & $this->mysqli->query ( $query )){
throw new Exception ( "<b><br>$query<br></b>" );
}
} else {
if ($use_result)
$result = & $this->mysqli->query ( $this->mysqli, $query, MYSQLI_USE_RESULT );
else
$result = & $this->mysqli->query ( $query );
}
$this->affected_rows = $this->mysqli->affected_rows;
return $result;
} catch ( Exception $erro ) {
trigger_error ( $erro->getMessage (), E_USER_WARNING );
}
return false;
}
/**
* stmt ile query oluşturur
*
* @param Array $res result Array
* @param string $query SQL
* @param Array $dataArr data array
* @return void
*/
private function stmtSelect($res, $query, $dataArr) {
$this->stmt = & $this->mysqli->stmt_init ();
try {
if ($this->stmt->prepare ( $query )) {
$result = & $this->stmt->result_metadata ();
$fieldArr = array ();
$_dataArr = array ();
$data = '';
while ( $finfo = $result->fetch_field () ) {
array_push($fieldArr, $finfo->name);
$data .= '$_dataArr[],';
}
$result->close();
$dataTypeArr = self::setDataType ( $dataArr );
@eval ( "\$this->stmt->bind_param(\$dataTypeArr[0]" . "," . $dataTypeArr [1] . ");" );
$data = self::setComma ( $data );
$this->stmt->execute ();
@eval ( "\$this->stmt->bind_result($data);" );
$this->stmt->store_result ();
$res->num_rows = $this->stmt->num_rows;
$ii = 0;
$len = $this->stmt->field_count;
while ( $this->stmt->fetch () ) {
if (is_array ( $dataArr )) {
for($i = 0; $i < $len; $i ++)
$res->dataArr[$ii][$fieldArr[$i]] = $_dataArr[$i];
}
$ii ++;
}
$this->db_state = true;
//mysqli_free_result($this->stmt);
}
else
{
throw new Exception("SQL : - {$query} -");
}
} catch ( Exception $error ) {
trigger_error ( $error->getMessage(), E_USER_ERROR );
}
}
/**
* select işlemini yapar.
* tüm class ve harici dosyalar tarafından çağrılabilir.
*
* @param boolean $res result object
* @param string $query sql
* @param boolean $trigger
* @return boolean
*/
public function select(&$res, $query, $dataArr = array(), $trigger = true) {
self::empty_results ( $res );
if ($this->debug) {
array_push ( $this->debugQuery, $query );
}
try {
if (count($dataArr)>0) {
self::stmtSelect ( $res, $query, $dataArr );
return true;
}
$result = & self::execute ( $query, $trigger );
@$num = $result->num_rows;
if ($num > 0) {
$res->num_rows = $num;
for($i = 0; $i < $res->num_rows; $i ++) {
$dataArr = $result->fetch_assoc ();
if (is_array ( $dataArr )) {
foreach ( $dataArr as $name => $value )
$res->dataArr [$i] [$name] = $value;
}
}
$this->db_state = true;
//$this->mysqli->free_result;
$result->close ();
//mysqli_free_result($result);
return true;
} else {
$this->db_state = true;
return false;
}
} catch ( Exception $error ) {
if ($trigger)
trigger_error ( $this->mysqli->error . "<b><br>$query<br></b>" . $error->getMessage (), E_USER_WARNING );
$this->db_state = false;
}
return false;
}
/**
* insert işlemini yapan method
*
* @param string $query
* @param Array $dataArr
* @param boolean $trigger
* @return boolean
*/
public function insert($query, $dataArr = array(), $trigger = true) {
if ($this->debug)
array_push ( $this->debugQuery, $query );
if (count($dataArr)==0) {
self::execute ( $query, $trigger );
return true;
}
try {
$this->stmt = & $this->mysqli->prepare ( $query );
$dataTypeArr = self::setDataType ( $dataArr );
#echo $query."-";getDebug($dataArr);getDebug($this->mysqli);
eval ( "\$this->stmt->bind_param(\$dataTypeArr[0]"."," . $dataTypeArr [1] . ");" );
if ($this->stmt->execute())
{
$this->affected_rows = $this->mysqli->affected_rows;
$this->db_state = true;
return true;
}
else
{
throw new Exception('Execute yapılamadı');
}
} catch ( Exception $error ) {
$this->db_state = false;
trigger_error ( $error->getMessage () . "<!-- $query \n".var_export($dataArr)."-->", E_USER_WARNING );
}
return false;
}
/**
* update işlemini yapan method
*
* @param string $query
* @param Array $dataArr
* @return boolean
*/
public function update($query, $dataArr = array(), $trigger = true) {
if ($this->debug)
array_push ( $this->debugQuery, $query );
if (count ( $dataArr ) == 0) {
self::execute ( $query, $trigger );
return true;
}
try {
$this->stmt = & $this->mysqli->prepare ( $query );
$dataTypeArr = self::setDataType ( $dataArr );
@eval ( "\$this->stmt->bind_param(\$dataTypeArr[0]" . "," . $dataTypeArr [1] . ");" );
$this->stmt->execute ();
$this->affected_rows = $this->mysqli->affected_rows;
$this->db_state = true;
return true;
} catch ( Exception $error ) {
$this->db_state = false;
trigger_error ( $error->getMessage (), E_USER_WARNING );
}
return false;
}
/**
* delete işlemini yapan method
*
* @param string $query
* @param Array $dataArr
* @param boolean $trigger
* @return boolean
*/
public function delete($query, $dataArr = array(), $trigger = true) {
if ($this->debug)
array_push ( $this->debugQuery, $query );
if (count ( $dataArr ) == 0) {
self::execute ( $query, $trigger );
return true;
}
try {
$this->stmt = & $this->mysqli->prepare ( $query );
$dataTypeArr = self::setDataType ( $dataArr );
eval ( "\$this->stmt->bind_param(\$dataTypeArr[0]" . "," . $dataTypeArr [1] . ");" );
$this->stmt->execute ();
$this->affected_rows = $this->mysqli->affected_rows;
$this->db_state = true;
return true;
} catch ( Exception $error ) {
$this->db_state = false;
trigger_error ( $error->getMessage (), E_USER_WARNING );
}
return false;
}
/**
* insert yapılan Id'yi verir
* tüm class ve harici dosyalar tarafından çağrılabilir.
*
* @return integer
*/
public function last_id() {
return $this->mysqli->insert_id;
}
/**
* transaction oluşturur
* tüm class ve harici dosyalar tarafından çağrılabilir.
*
* @param boolean $autocommit
* @return boolean
*/
public function startTransaction($autocommit = false) {
try {
$this->mysqli->autocommit ( $autocommit );
return true;
} catch ( Exception $error ) {
trigger_error ( $error->getMessage (), E_USER_ERROR );
}
return false;
}
/**
* oluşan transaction için commit yapar
* tüm class ve harici dosyalar tarafından çağrılabilir.
*
* @return void
*/
public function commit() {
try {
$this->mysqli->commit ();
} catch ( Exception $error ) {
trigger_error ( $error->getMessage (), E_USER_ERROR );
}
}
/**
* oluşan transaction'u geri alır
* tüm class ve harici dosyalar tarafından çağrılabilir.
*
* @return void
*/
public function rollback() {
try {
$this->mysqli->rollback();
} catch ( Exception $error ) {
trigger_error ( $error->getMessage (), E_USER_ERROR );
}
}
/**
* işlem bittiğinde bağlantı kopartılır
* tüm class ve harici dosyalar tarafından çağrılabilir.
*
* @param void
*/
public function __destruct() {
try {
if (is_resource ( $this->mysqli ))
$this->mysqli->close ();
} catch ( Exception $error ) {
trigger_error ( $error->getMessage (), E_USER_ERROR );
}
}
/**
* Bilinmeyen method
* tüm class ve harici dosyalar tarafından çağrılabilir.
*
* @return boolean
*/
public function __clone() {
trigger_error ( 'Bilinmeyen bir method', E_USER_ERROR );
return false;
}
/**
* obje'yi echo veya print ettiğimizde çağrılan toString fonskiyonu
*
* @return boolean
*/
public function __toString() {
trigger_error ( 'Obje direk echo yapılamaz', E_USER_ERROR );
return false;
}
/**
* mysql info bilgilerini verir.
* tüm class ve harici dosyalar tarafından çağrılabilir.
*
* @return string
*/
public function stat() {
return $this->mysqli->stat ();
}
/**
* error message
*
* @return string
*/
public function errorMessage() {
return mysqli_stmt_error ( $this->stmt );
}
/**
* IN için sondan virgün kaldırır.
*
* @param dataListe $commaList
* @return string
*/
private function setComma($commaList)
{
if ( substr($commaList,-1) == ',' )
return substr($commaList,0,-1);
else
return $commaList;
}
}
?>
db class'ı verdikten sonra select metohodunu kullanırken dönen verileri map yapacağımız ayrıca bir class'a daha ihtiyacımız olacak. Bunuda aşağıda verdik.
<?php
/**
* data'yı çeviren class
*
* @author Mehmet Şamlı
*/
class dbResult
{
/**
* Query sonucunda dönen satır sayısı
*
* @var integer
*/
public $num_rows;
/**
* Query sonucunda oluşan data'nın aktarılacağı Array
*
* @var array
*/
public $dataArr;
/**
* Genel çalışma methodu
*
* @return void
*/
public function __construct()
{
$this->num_rows = 0;
$this->dataArr = array();
}
}
?>
Tüm kaynak kodlarını verdikten sonra, şimdide bu class'ı nasıl kullanabileceğimizi belirtelim.
INSERT
İlk olarak veritabanına bağlanabilmemiz için gerekli kimlik bilgilerini define olarak tanımlıyoruz. Zira db class'ın __construct methodunda mysqli class'ını çağırırken bu sabitleri kullanıyoruz. Daha sonra db class'ını çağırıp sql cümleciğini prepare yöntemi olarak oluşturuyoruz. Sonrasında transaction methodunu çağırıp, insert metoduna sırasıyla sql cümleciği ile bu sql cümleciğinde yer alan parametrelere denk gelecek değerleri bir array değeri olarak gönderiyoruz. Hepsi bukadar. <?php
define('db_host','127.0.0.1');
define('db_user','root');
define('db_pass','');
define('db_dbName','dbname');
define('db_port','3306');
define('db_character','utf8');
require_once('class/db.class.php');
$DB = new db();
$sql="INSERT INTO articles (category_id,name,description,regDate) VALUES (?,?,?,NOW())";
$dataArr = array(1,'isim','açıklama alanı');
$DB->startTransaction();
$DB->insert($sql,$dataArr);
$DB->commit();
printf("Toplam <b>%s</b> kayıt eklendi.",$DB->affected_rows);
?>
SELECT
Select cümleciğinde ise tıpkı insert cümleciğinde olduğu gibi sql cümleciğini prepare yöntemiyle oluşturuyoruz. Lakin select metodunda ilk olarak önceden oluşturduğumuz dbResult objesini, sonrasında sql cümleciği, son olarakda prepare'de yer alan parametre değerlerini array olarak giriyoruz. Tüm veriler select methodu sorgu sonucundan dönen tüm değerleri $result objesine yükleyecektir. <?php
define('db_host','127.0.0.1');
define('db_user','root');
define('db_pass','');
define('db_dbName','dbname');
define('db_port','3306');
define('db_character','utf8');
require_once('class/db.class.php');
require_once('class/dbResult.class.php');
$DB = new db();
$result = new dbResult();
$sql="SELECT * FROM articles WHERE id=?";
$DB->select($result,$sql,array(5));
print_r($result);
?>
