05-03-2009, 12:27
|
|
|
|
חבר מתאריך: 11.03.07
הודעות: 1,668
|
|
כל הכבוד שהבאת את כל המידע והסברת את הנושא ממש טוב...
התעסקתי בשאלה של PDO או MYSQLi המון לפני לא כל כך הרבה זמן, והגעתי למסקנה שאני אמשיך לעבוד עם MySQLi.
אחת הסיבות העיקריות היא מהירות, שכמו שאפשר לראות ברוב ה BENCHMARKS ש- PDO איטי בהרבה.
עוד סיבה עיקרית היא שאין צורך בעוד שכבת עיבוד מידע כדי לעבוד עם המסד נתונים, אלא אם באמת - וכאן הגדולה של PDO - אתה הולך להחליף מסדי נתונים על בסיס קבוע.
אין כמו MySQLi לעבודה עם MySQL.
אגב, עשיתי כמה שינויים לclass של ה MySQLi כדי שיתאים לצרכים שלי ולצורת העבודה שלי - וזה משלב לי את ההגנות מSQL INJECTIONS של MySQLi והנוחות של ביצוע שאילתות בסיסי של MySQL... (אגב עוד משהו שנהדר בMySQLi זה שהוא קיים גם בצורת OOP מה שמאפשר שינויים בלי להתחיל ליצור עוד פונקציות מסביב לכל מה שכבר יש...)
השתמשתי בכמה דברים שראיתי בכל מיני קבוצות דיון ובאתר php.net והוספתי קצת שינויים שלי, כמו הצורך בלהשאיר את השאילתה פתוחה ולא לסגור אותה (->close()) אך כמו כן תמיד לסגור אותה בסוף שימוש כדי להמשיך לשאילתה הבאה.
קוד PHP:
<?php class mysqli_extended extends mysqli { public function __construct($dbHost, $dbUsername, $dbPassword, $dbDatabase) { parent::__construct($dbHost, $dbUsername, $dbPassword, $dbDatabase); } public function prepare($query) { $stmt = new stmt_extended($this, $query); return $stmt; } public function execQuery($call,$types='',$params=array()) { $stmt = $this->prepare($call); if (count($params) > 0) { $bind_names[] = $types; for ($i=0; $i<count($params);$i++) { $bind_name = 'bind' . $i; $$bind_name = $params[$i]; $bind_names[] = &$$bind_name; } call_user_func_array(array($stmt,'bind_param'),$bi nd_names); } $stmt->execute(); $stmt->store_result(); return $stmt; } } class stmt_extended extends mysqli_stmt { protected $varsBound = false; protected $results; public function __construct($link, $query) { parent::__construct($link, $query); } public function fetch_assoc() { // checks to see if the variables have been bound, this is so that when // using a while ($row = $this->stmt->fetch_assoc()) loop the following // code is only executed the first time if (!$this->varsBound) { $meta = $this->result_metadata(); while ($column = $meta->fetch_field()) { $columnName = str_replace(' ', '_', $column->name); $bindVarArray[] = &$this->results[$columnName]; } call_user_func_array(array($this, 'bind_result'), $bindVarArray); $this->varsBound = true; } if ($this->fetch() != null) { foreach ($this->results as $k => $v) $results[$k] = $v; return $results; } else { // this executes on the last time fetch_assoc() is being called in a loop; as I have no more use of the prepared statement, close it. $this->close(); return null; } } public function num_rows() { // altered num_rows to close the prepared statement after retrieving number of rows, as my execQuery does not ->close(). // (can always still use ->num_rows before a ->fetch_assoc() to retrieve it without closing.) $num_rows = $this->num_rows; $this->close(); return $num_rows; } } ?>
אני יוצר חיבור בצורה הבאה:
קוד PHP:
$mysqli = new mysqli_extended('server', 'user', 'password', 'database'');
ומריץ שאילתות בצורה הבאה:
קוד PHP:
$result = $mysqli->execQuery('SELECT * FROM table WHERE id=? AND name=?', 'is', array($_REQUEST['id'], $_REQUEST['name'])); $num_rows = $result->num_rows; for ($i = 0; $row = $result->fetch_assoc(); $i++) { echo 'header: '. $row['header'] .' message: '. $row['message']; }
אם אין לי שימוש בfetch_assoc() בשאילתה כלשהי אלא רק למצוא את מספר השורות שנבחרו, אפשרי פשוט להשתמש בצורה הבאה:
קוד PHP:
$num_rows = $mysqli->execQuery('SELECT 1 FROM table WHERE id=? AND name=?', 'is', array($_REQUEST['id'], $_REQUEST['name']))->num_rows();
ו num_rows() כבר ידאג לסגור (->close()) את השאילתה, וכמובן להחזיר את כמות השורות שנבחרו.
אם אין צורך בלולאה, לדוגמא אם התוצר אמור להיות רק שורה אחת או כלום (LIMIT 1) ואין צורך בכמות השורות הקיימת - אפשר פשוט לבצע את השאילתה בצורה הבאה:
קוד PHP:
$row = $mysqli->execQuery('SELECT * FROM table WHERE id=? AND name=?', 'is', array($_REQUEST['id'], $_REQUEST['name']))->fetch_assoc();
אם יש למישהו הערות או הארות לגבי צורת השימוש שלי ב MySQLi אני אשמח לשמוע, פעם ראשונה שאני מציג את זה לפני אנשים אחרים...
|