PDA

View Full Version : سوال: استفاده از کلاسها در php - اشکال این کد چیه؟



tafo2066
شنبه 13 فروردین 1390, 20:09 عصر
سلام، من تو php مبتدی ام و سوالاتی دارم.
من کد زیر رو برای ارتباط با دیتابیس نوشتم- با استفاده از کلاسها - حالا این کد خطا میده به هر منبعی رجوع کردم درست بود. حالا میخوام از شما بپرسم.
و سوال دیگه اینکه آیا اینطوری کد نوشتن کار درستیه؟

کد کلاس:


<?php
/**
* DataBase Class For Connect,Disconnect,Execute & ...
*
* Copyright: 2011
* Author: Foad Tahmasebi
*
* Start Date: 01-04-2011
*
*/

class database {

var $db_host = "localhost";
var $db_name = "test1";
var $db_user = "root";
var $db_pass = "";
var $db_prefix ="";

var $connection;
var $database;
var $result;

// Connect to data base usage connect_db("localhost","username","password");
function connect_db($db_host,$db_user,$db_pass){
$this->connection = mysql_connect($db_host,$db_user,$db_pass);
if (!$this->connection){
die('Could not connect: ' . mysql_error());
}
}

function select_db($db_name,$connection){
$this->database = mysql_select_db($db_name,$connection);
if (!$db->database){
die('Could Not Select DB: ' . mysql_error());
}
}

/* Execute Query, Usage: database::query("SELECT * FROM table_name");
* Use this function on your php, it's enough!
*/
function query($query){
if($this->connect_db($this->db_host,$this->db_user,$this->db_pass)){
if($this->select_db($this->db_name, $this->connection)){
$result = mysql_query($query);
if (!$result){
die('Query Failed: ' . mysql_error());
return $result;
$this->close_db ($this->connection);
}
else{
return $result;
$this->close_db ($this->connection);
}
}
}
}

function close_db ($connection){
mysql_close($connection);
}
}
?>


کد فراخوانی و کووری:


<?php
require_once "class/database.php";

$res = database::query("
CREATE TABLE Persons(
P_Id int,
LastName varchar(255),
FirstName varchar(255),
Address varchar(255),
City varchar(255))
");
if ($res){echo "ok";}
else {echo "not";}

?>

MMSHFE
شنبه 13 فروردین 1390, 20:15 عصر
با سلام، دوست گرامي شما متد رو ازطريق نام كلاس فراخواني كردين. براي حل مشكل، يا متد رو به صورت static در بيارين. راستي، چرا كلمه public رو قبل از متد query ننوشتين؟ طبق اصول شئ گرايي، اگه صراحتاً سطح دسترسي يك عنصر از كلاس رو مشخص نكنيد، به طور پيشفرض خودش private درنظر ميگيره و بيرون از كلاس، قابل دسترسي نخواهد بود:


public static function query($query){
//statements
}

و يا اينكه يك شئ از كلاس ايجاد كرده و ازطريق شئ به متد دسترسي داشته باشين:


$db = new database();
$res = $db->query('YOUR QUERY');

موفق باشيد.

tafo2066
شنبه 13 فروردین 1390, 21:41 عصر
اینم کد اصلاح شده بالا و با راهنمایی آقای MMSHFE (خیلی سخته تلفظ کردنش :چشمک:) سوال دوم ام جواب بدید ممنون میشم: آیا استفاده از این روش برای اجرای کووری و اتصال به پایگاه داده کار درستیه؟


<?php
/**
* DataBase Class For Connect,Disconnect,Execute & ...
*
* Copyright: 2011
* Author: Foad Tahmasebi
*
* Date: 02-04-2011
*
*/

class database {

var $db_host = "localhost";
var $db_name = "test1";
var $db_user = "root";
var $db_pass = "";

var $connection;

// Connect to data base usage connect_db("localhost","username","password","dbname");
function connect_db($db_host,$db_user,$db_pass,$db_name){
$this->connection = mysql_connect($db_host,$db_user,$db_pass);
if ($this->connection){
$database = mysql_select_db($db_name,$this->connection);
if ($database){
return true;
}
else{
die('Could Not Select DB: ' . mysql_error());
return false;
}
}
else{
die('Could not connect: ' . mysql_error());
return false;
}

}

/* Execute Query, Usage: $db = new database(); $db->query("SELECT * FROM table_name");
* Use this function on your php, it's enough!
*/
function query($query){
if($this->connect_db($this->db_host,$this->db_user,$this->db_pass,$this->db_name)){
$result = mysql_query($query);
if ($result){
$this->close_db($this->connection);
return $result;
}
else{
die('Query Failed: ' . mysql_error());
$this->close_db($this->connection);
return false;
}
}
}

function close_db ($connection){
mysql_close($connection);
}
}
?>

Mr.Moghadam
شنبه 13 فروردین 1390, 21:48 عصر
آیا استفاده از این روش برای اجرای کووری و اتصال به پایگاه داده کار درستیه؟

معمولا توی کلاسهایی که برای کار با پایگاه داده است دستورات CURD رو به صورت توابع جدا مینویسن.یعنی یه متود برای select یکی برای آپدیت یکی برای insert یکی برای delete.یکی از کزیت های این روش اینه که شما نیازی نیست همیشه کوئری بنویسن و به جاش یه سری مقادی رو به متود مورد نظر پاس میدین و اون بقیه کارا رو براتون انجام میده.
مثلا برای select :



public function select($table,$filter="",$orderby="",$limit = '')
{
$filter = $this->escape($filter);
$orderby = $this->escape($orderby);
$sql = "select * from $table";

if(!empty($orderby))
$sql .= " ORDER BY $orderby";

if(!empty($filter))
$sql .= " WHERE $filter";

if(!empty($limit))
$sql .= " LIMIT $limit";
//echo $sql;
$result=mysql_query($sql)or die (mysql_error());
return $result;
}


موفق باشید

hosseintdk775
دوشنبه 15 فروردین 1390, 17:14 عصر
باگه صراحتاً سطح دسترسي يك عنصر از كلاس رو مشخص نكنيد، به طور پيشفرض خودش private درنظر ميگيره و بيرون از كلاس، قابل دسترسي نخواهد بود:

بسم الله الرحمن الرحیم
سلام
اشتباه نمی کنید؟
اینجا رو بخون:

Class methods may be defined as public, private, or protected. Methods declared without any explicit visibility keyword are defined as public.
اینم منبش: http://php.net/manual/en/language.oop5.visibility.php

یعنی اکه تعیین نشه public میشه نه private

پ.ن: در مورد اصول شی گرائی نمی دونم ولی در php اینگونه هست / البته تا جایی که می دونم php دقیقا اصول شیئ گرایی رو رعایت نمی کنه ( شاید تو زبان های دیگه private باشه )

Sajjad.Aghapour
دوشنبه 15 فروردین 1390, 19:30 عصر
یعنی اکه تعیین نشه public میشه نه private

منظور این دوستمون Variable ها بوده که البته برای Variable ها در PHP باید صراحتا Visibility مشخص بشه(متغیرهای سراسری در سطح کلاس) ولی Method ها بطور پیش فرض Public درنظر گرفته میشن

hosseintdk775
دوشنبه 15 فروردین 1390, 20:31 عصر
منطورتون از Variable همون property ها هست دیگه؟
خوب واسه پروپرتی ها هم همینطوره دیگه / اگه مشخص نشه public هست نه private
تو همون لینک هم نوشته / و تست هم کردم public بود نه private

Class properties must be defined as public, private, or protected. If declared using var without an explicit visibility keyword, the property will be defined as public.

Sajjad.Aghapour
دوشنبه 15 فروردین 1390, 22:33 عصر
منطورتون از Variable همون property ها هست دیگه؟
خوب واسه پروپرتی ها هم همینطوره دیگه / اگه مشخص نشه public هست نه private
تو همون لینک هم نوشته / و تست هم کردم public بود نه private
Class properties must be defined as public, private, or protected. If declared using var without an explicit visibility keyword, the property will be defined as public.
خیر.
Property ها معمولا برای ارسال و دریافت مقادیر و مقداردهی به متغیرهای کلاس به کار گرفته میشه و عملا مانند متدها عمل میکنن. برای رعایت اصول شی گرایی که وقتی صحبت از Global Variable ها به میون میاد اصل Encapsulation و Data Hiding یا Information Hiding خودش رو نشون میده و عدم استفاده از Global Variable ها رو در شی گرایی برای شما توجیه میکنه که در اینجا شما میتونید از متدهای Parametric یا Property ها استفاده کنید(در این مورد میتونید تحقیق کنید)...
منظور از Variable همین متغیرهای عادی هست که در کلاس تعریف میشه. اگر سطح دسترسی برای اونها تعریف نشه بطور پیش فرض اونها Private در نظر گرفته میشن:



class Test
{
private $var_1 = 'test'; //
$var_2 = 'test'; // Error!
public $var_2 = 'test'; // no problem, but it's against OOP
private function Method_1(){} //
function Method_2(){} // This function is public
}

MMSHFE
دوشنبه 15 فروردین 1390, 23:26 عصر
با سلام، حقيقتش چون خودم هميشه سطح دسترسي رو صراحتاً تعريف ميكنم، به اين مورد بر نخورده بودم. اتفاقاً خوب شد كه اين مسئله رو گفتين و خوشحالم كه متوجه شدم در اين مورد PHP اصول شئ گرايي رو نقض كرده و به بخش Support تيم Zend ايميل زدم و خوشبختانه گفتن در نسخه 6 اين مورد رفع شده و هر عنصري از كلاس (متد، فيلد و...) اگه سطح دسترسي رو براش صراحتاً ذكر نكنيم، private خواهد بود. بنابراين بهتره از الآن عادت كنيد كه صريحاً سطح دسترسي رو ذكر كنيد.
موفق باشيد.

mtchabok
سه شنبه 16 فروردین 1390, 09:04 صبح
عزیزان
سطح دسترسی در php به صورت پیشفرض public هس و اون در زبانهایی مثل c# هس که سطحش private میشه و البته در php چونکه یه زبان تحت سرور هس به صورت public در نظر گرفته شده . تا طراحان و برنامه نویسان درگیر کدهای اعمال محدودیت نباشن . ولی در زبانهایی مثل c# چونکه همه چی باید صریح تعریف بشه بدین صورت هس .

خوب حالا جواب این دوستمون که کلاس رو نوشتن باید بگم که شما در متدهایی که نوشتید از $this استفاده کردید ولی در فراخوانی متدها به صورت static عمل کردید . به همین خاطر هس که کلاستون کار نمیکنه .
دو راه حل دارید :
- روش اول اینکه کلاستون رو به صورت static در بیارید و تمامی property ها و متدهاتون رو به صورت استاتیک فراخوانی کنید .
- روش دوم اینه که از کلاس فعلیتون یه شئی ایجاد کنید و توسط شئی کارتون رو انجام بدید .

برای روش اول کلاستون رو به این صورت تغییر بدید :

<?php
/**
* DataBase Class For Connect,Disconnect,Execute & ...
*
* Copyright: 2011
* Author: Foad Tahmasebi
*
* Start Date: 01-04-2011
*
*/

class database {

static $db_host = "localhost";
static $db_name = "test1";
static $db_user = "root";
static $db_pass = "";
static $db_prefix ="";

static $connection;
static $database;
static $result;

// Connect to data base usage connect_db("localhost","username","password");
static function connect_db($db_host,$db_user,$db_pass){
self::$connection = mysql_connect($db_host,$db_user,$db_pass);
if (!self::$connection){
die('Could not connect: ' . mysql_error());
}
}

static function select_db($db_name,$connection){
self::$database = mysql_select_db($db_name,$connection);
if (!self::$database){
die('Could Not Select DB: ' . mysql_error());
}
}

/* Execute Query, Usage: database::query("SELECT * FROM table_name");
* Use this function on your php, it's enough!
*/
static function query($query){
if(self::$connect_db(self::$db_host,self::$db_user ,self::$db_pass)){
if(self::$select_db(self::$db_name, self::$connection)){
$result = mysql_query($query);
if (!$result){
die('Query Failed: ' . mysql_error());
return $result;
self::$close_db (self::$connection);
}
else{
return $result;
self::$close_db (self::$connection);
}
}
}
}

static function close_db ($connection){
mysql_close($connection);
}
}
?>
و برای استفاده همونطوریکه نوشتید درسته .

روش دوم فقط نحوه استفاده رو یه ویرایش میخواد :

<?php
require_once "class/database.php";

$db = new database();

$res = $db->query("
CREATE TABLE Persons(
P_Id int,
LastName varchar(255),
FirstName varchar(255),
Address varchar(255),
City varchar(255))
");
if ($res){echo "ok";}
else {echo "not";}

?>

موفق باشید

tafo2066
پنج شنبه 18 فروردین 1390, 17:31 عصر
خیلی ممنون از همه دوستانی که راهنمایی کردند.
میخواستم بدونم فرق بین این دو نوع تعریف چیه؟ یعنی چه فرقی میکنه اگه ما استاتیک کلاس رو بنویسیم یا یک شی بسازیم و از اون استفاده کنید؟ از لحاظ کد نویسی که هر دو در یک سطحه!

mtchabok
پنج شنبه 18 فروردین 1390, 21:01 عصر
فرقشون در اینه که شما میخواید که کلاستون یه مجموعه متد (تابع) باشه و یا میخواید که همچنین از قابلیت های شئی گرایی هم استفاده کنید .
اگه میخواین که کلاستون فقط یه مجموعه متد باشه می بایست واژه static رو در کنار متدهاتون بزارید تا مثل یه تابع فراخوانی بشن .
اگه میخواین از قابلیت های شئی گرایی استفاده کنین بهتره که متدهای موجود رو static نزارید تا بتونید در شئی هایی که از کلاس ایجاد میکنید بتونید از تابع ها استفاده کنید .
یه مثال از ایجاد شئی میزنم :

<?php
class a{

var $property;

function change($newProperty){
$this->property = $newProperty;
}

}

$x = new a();
$y = new a();

$x->change('testx');
$y->change('testy');

echo '$x->property => '.$x->property."<br>"; // $x->property => testx<br>
echo '$y->property => '.$y->property; // $y->property => testy

?>

خوب حالا یه مثال از حالت static در متدها و یا پروپرتیها :

<?php
class a{

static $property;

static function change($newProperty){
$this->property = $newProperty;
}

}

a::change('text1');
a::change('text2');
echo a::$property; // test2
a::change('text3');
echo a::$property; // test3

?>

خوب اینم از مثالها ...
ببین معمولا من خودم زمانی از حالت استاتیک استفاده می کنم که میخوام متد در کلاس مثل یه تابع اجرا بشه . البته این دو حالتی که گفتم الزامی نیس که همه static و یا همه نباشه ... ما میتونیم ترکیبی از این دو حالات رو هر جایی استفاده کنیم .
برای اطلاعات بیشتر سری به تاپیک OOP (http://barnamenevis.org/showthread.php?83103-%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-OOP) بزنید .

tafo2066
شنبه 20 فروردین 1390, 00:05 صبح
خیلی از لطفتون ممنونم. یه سوال دیگه،
اگر من اتصال به دیتابیس رو در __construct() و قطع ارتباط رو در __destruct() بنویسم بهتره؟ یا یه تابع جدا که تو برنامم فراخوانی شه؟

mtchabok
شنبه 20 فروردین 1390, 09:14 صبح
به طور معمولا ما سعی میکنیم که فراخوانی برخی کدها دست خودمون باشه ولی به طور کلی اینکار وابسته به نحوه استفاد شما داره .
متد __construct در هنگام ایجاد شئی اجرا میشه و متد __destruct هم در هنگام از بین رفتن شئی . خوب حالا این بستگی که استفاده شما داره که آیا کدهای مربوط به اتصال و قطع از دیتابیس رو به صورت اتوماتیک میخواید یا نه .
ولی معمولا همونطوریکه گفتم این نوع کدها رو در متدهای جداگانه مینویسیم و اگه نیاز بود به صورت اتوماتیک اجرا بشوند در متدهای ذخیره شده اونا رو فراخوانی میکنیم . تا اگه خواستیم به صورت دستی اونرو اجرا کنیم با مشکل مواجه نشیم .
امیدوارم که منظورم رو درست نوشته باشم .