From Shabgard.ORG

PHP
آشنايي با ماژول Mysqli در PHP 5
By www.iranphp.net
Jan 16, 2005, 22:24

يكي از ويژگي هاي جالبي كه در php 5 ارائه شده است يك Extension جديد به نام ext/mysqli مي باشد كه همانند ext/mysql سابق به عنوان يك رابط براي كار با پايگاه داده mysql از آن استفاده مي شود. برای برنامه های کاربردی در مقیاس بزرگتر ماژول جدید MySQLi به کاربران اجازه می دهد که از ویژگی های جدید MySQL 4.1 در برنامه های خود استفاده کنند که بازدهی بیشتری را نسبت به نسخه های قبلی MySQL فراهم می کند.

از اواسط دهه 90 تاكنون ext/mysql نقش خود را به عنوان يك پل رابط ميان PHP و MySQL به خوبي ايفا كرده است. اگرچه ext/mysql نقاط ضعف كمي داشته است ولي توانسته است كه همگام با تغييرات PHP و MySQL پيش رود.



اما وقتي كه PHP 5 و MySQL 4.1 پا به عرصه نهادند ext/mysql نشان داد كه براي سازگاري با پيشرفت هاي زياد اين دو نسخه، فقدان هايي را دارد.يكي از اين نفاط ضعف مربوط به برقراري ارتباط پايدار و دايمي با پايگاه داده (mysql_pconnect()) بود. ويژگي ها و امكاناتي توسط MySQL ارائه شد كه ext/mysql هنوز قادر به سازگاري با آنها نبود. براي رفع اين مشكلات Georg Richter شروع به ساخت يك extension جديد براي PHP 5 كرد كه با ويژگي هاي ارائه شده در MySQL 4.1 و نسخه هاي بالاتر همگام باشد.



مهمترين ويژگي هاي ارائه شده توسط ext/mysqli



ارائه يك واسط روالي (Procedural Interface) كه بسيار شبيه واسط ext/mysql مي باشد
ارائه يك واسط شي گرا(Object-Oriented Interface) كه در مقايسه با واسط روالي از انعطاف پذيري بيشتري برخوردار است و كار با آن راحت تر است(با توجه به امكانات شي گرايي در PHP 5)
پشتيباني از پروتكل باينري جديد MySQL كه در نسخه 4.1 عرضه شد.(اين پروتكل جديد در مقايسه با قبلي از بازدهي بيشتري برخوردار است و امكانات گسترده اي همچون Prepared Statement را پشتيباني مي كند.)
پشتيباني از تمام ويژگي هاي مجموعه كتابخانه كاربري MySQL C كه شامل قابليت تنظيم گزينه هاي پيشرفته اتصال از طريق mysqli_init() و توابع وابسته مي شود.


به دو دليل توصيه مي شود كه به اين ماژول جديد switch كنيد و از اين به بعد با اين ماژول كار كنيد:

سرعت بيشتر
امنيت بيشتر




حرف i در انتهاي ext/mysqli به معناي ,improved, interface, ingenious, incompatible incomplete مي باشد!



نحوه كار با ext/mysqli



*قبل از كدنويسي توجه داشته باشيد كه براي استفاده از اين ماژول، شما بايد PHP 5 و MySQL 4.1 را نصب كرده باشيد.كدهاي اين مقاله از پايگاه داده World استفاده مي كنند كه به صورت رايگان از آدرس http://www.mysql.com/documentation/index.html قابل دريافت مي باشد.



برنامه ساده زير ابتدا به پايگاه داده متصل مي شود و با ارسال يك پرس و جو(Query) به Server ، دريافت نتايج و نمايش آنها و سپس بستن اتصال به كار خود خاتمه مي دهد:



<?php

/* Connect to a MySQL server */
$link = mysqli_connect(
            
'localhost',  /* The host to connect to */
            
'user',       /* The user to connect as */
            
'password',   /* The password to use */
            
'world');     /* The default database to query */

if (!$link) {
   
printf("Can't connect to MySQL Server. Errorcode: %s\n\", mysqli_connect_error());
   exit;
}

/* Send a query to the server */
if ($result = mysqli_query($link, 'SELECT Name, Population FROM City ORDER BY Population DESC LIMIT 5')) {

    print(\"Very large cities are:\n\");

    /* Fetch the results of the query */
    while( $row = mysqli_fetch_assoc($result) ){
        printf(\"%s (%s)\n\", $row['Name'], $row['Population']);
    }

    /* Destroy the result set and free the memory used for it */
    mysqli_free_result($result);
}

/* Close the connection */
mysqli_close($link);
?>



بعد از اجراي اسكريپت بالا بايد خروجي را به صورت زير مشاهده كنيد:




Very large cities are:

Mumbai (Bombay) (10500000)
Seoul (9981619)
São Paulo (9968485)
Shanghai (9696300)
Jakarta (9604900)




همانطور كه در كد مشاهده مي كنيد در اينجا هيچ تفاوت خاصي بين ext/mysql و ext/mysqli مشاهده نمي شود جز افزوده شدن حرف i به آخر توابع!



حال اگر از واسط شي گرا استفاده كنيد و برنامه بالا را مجددا بازنويسي كنيد به انعطاف پذيري بيشتر و راحتي كار با اين واسط جديد پي مي بريد:


<?php

/* Connect to a MySQL server */
$mysqli = new mysqli('localhost', 'user', 'password', 'world');

if (
mysqli_connect_errno()) {
   
printf("Can't connect to MySQL Server. Errorcode: %s\n\", mysqli_connect_error());
   exit;
}

/* Send a query to the server */
if ($result = $mysqli->query('SELECT Name, Population FROM City ORDER BY Population DESC LIMIT 5')) {

    print(\"Very large cities are:\n\");

    /* Fetch the results of the query */
    while( $row = $result->fetch_assoc() ){
        printf(\"%s (%s)\n\", $row['Name'], $row['Population']);
    }

    /* Destroy the result set and free the memory used for it */
    $result->close();
}

/* Close the connection */
$mysqli->close();
?>





همانطور كه مشاهده مي كنيد اطلاعات مربوط به اتصال در اشياي $mysqli و $result ثبت مي شود و براي اجراي دستورات نيازي به مشخص كردن اين اطلاعات نداريم. همچنين وقتي در بين نتايج پرس و جو به صورت سطر به سطر توسط تابع fetch_assoc() حركت مي كنيم ديگر نيازي به ساخت يك handle براي كار با ركوردها نداريم.



استفاده از ويژگي Prepared Statements در پرس و جوها



مزيت Prepared Statements اين است كه به كاربران امكان ساخت query هاي بسيار ايمن تر، با بازدهي بيشتر و راحت تر را مي دهد. به دو صورت مي توان از اين ويژگي بهره برد: bound parameter prepared statements و bound result prepared statements



bound parameter prepared statements اين امكان را به ما مي دهد كه براي Query هاي خود قالب (Template) درست كنيم و آنها را در Server ذخيره كنيم. وقتي نياز به اجراي Query داشتيم اطلاعات لازم را براي پر كردن Query به Server مي فرستيم و سپس Query كامل را اجرا مي كنيم. اين كار دو مزيت دارد:

اول اينكه زمان كمتري صرف تجزيه و تحليل Query در هنگام اجرا مي شود. و دوم اينكه از حملات تزريقي SQL(SQL injection attacks) جلوگيري مي شود.

در زير يك مثال كامل از به كارگيري اين ويژگي را در پرس و جوها مشاهده مي كنيد:


<?php
$mysqli
= new mysqli('localhost', 'user', 'password', 'world');

/* check connection */
if (mysqli_connect_errno()) {
    
printf("Connect failed: %s\n\", mysqli_connect_error());
    exit();
}

$stmt = $mysqli->prepare(\"INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)\");
$stmt->bind_param('sssd', $code, $language, $official, $percent);

$code = 'DEU';
$language = 'Bavarian';
$official = \"F\";
$percent = 11.2;

/* execute prepared statement */
$stmt->execute();

printf(\"%d Row inserted.\n\", $stmt->affected_rows);

/* close statement and connection */
$stmt->close();

/* Clean up table CountryLanguage */
$mysqli->query(\"DELETE FROM CountryLanguage WHERE Language='Bavarian'\");
printf(\"%d Row deleted.\n\", $mysqli->affected_rows);

/* close connection */
$mysqli->close();
?>





توجه كنيد كه تابع bind_param() يك رشته كوتاه را به عنوان اولين پارامتر خود مي گيرد. اين پارامتر String Format مي باشد و نوع متغيرهاي ارسالي را مشخص مي كند. در مثال بالا sssd مشخص مي كند كه $code و $language و $official از نوع String مي باشند و $percent از نوع float يا Double مي باشد. مشخص كردن اين نوع داده ها باعث مي شود كه ext/mysqli بداند كه چگونه داده ها را براي فرستادن كدگذاري كند و اين كار باعث بازدهي بالا مي شود.جدول زير نوع داده هاي قابل قبول را نشان مي دهد:




BIND TYPE
COLUMN TYPE

i
All INT types

d
DOUBLE and FLOAT

b
BLOBs

s
All other types





اگر با ASP.NET هم آشنايي داريد، در زير مي توانيد نحوه به كارگيري اين ويژگي را درASP.NET هم مشاهده كنيد و با PHP 5 مقايسه كنيد:




Dim cnn As New SQLConnection(\"server=LOCALHOST;User id=SA;password=;database=Northwind\")
Dim InsertCommand As SqlCommand = New SqlCommand()
InsertCommand.Connection = cnn
Dim sql As String
sql = \"INSERT INTO categories (categoryName) VALUES (@newCatName)\"

InsertCommand.CommandText = sql

InsertCommand.Parameters.Add(\"@newCatName\", SqlDbType.NVarChar, 250).Value = \"Category Name\"




Bound result prepared statements اين امكان را مي دهد كه مقدار فيلدهاي دريافتي از پايگاه داده را به متغير هاي دلخواه نسبت دهيم(چيزي شبيه تابع list كه عناصر يك آرايه را به متغير هاي دلخواه نسبت مي دهد.)

مثال زير استفاده از اين ويژگي را نشان مي دهد:


<?php
$mysqli
= new mysqli("localhost\", \"user\", \"password\", \"world\");

if (mysqli_connect_errno()) {
    printf(\"Connect failed: %s\n\", mysqli_connect_error());
    exit();
}

/* prepare statement */
if ($stmt = $mysqli->prepare(\"SELECT Code, Name FROM Country WHERE Code LIKE ? LIMIT 5\")) {

    $stmt->bind_param(\"s\", $code);
    $code = \"C%\";

    $stmt->execute();

    /* bind variables to prepared statement */
    $stmt->bind_result($col1, $col2);

    /* fetch values */
    while ($stmt->fetch()) {
        printf(\"%s %s\n\", $col1, $col2);
    }

    /* close statement */
    $stmt->close();
}
/* close connection */
$mysqli->close();

?>




Copyright by Shabgard.ORG