Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Цикл mysql_fetch_array - зачем он нужен?

76K
20 ноября 2012 года
t3rmin41
14 / / 26.02.2012
Разбираю пример на php.net:

Код:
$query = "SELECT Name, CountryCode FROM City ORDER by ID DESC LIMIT 50,5";

$result = mysqli_query($link, $query)

    /* fetch associative array */
    //!!!!!!!
    while ($row = mysqli_fetch_assoc($result)) {
        printf ("%s (%s)\n", $row["Name"], $row["CountryCode"]);
    }
    //!!!!!!

    /* free result set */
    mysqli_free_result($result);
Исходя из этого когда, после этой строки:

 
Код:
$result = mysqli_query($link, $query)
в переменной $result появляется вся таблица выборки (или, если хотите, двумерный массив) в нечитаемой форме (бинарной или какой-то ещё, неважно). Почему я так решил? Потому что больше нигде ничего в переменную $result не заносится. Теперь вопрос - не должно ли быть какой-либо функции, возвращающей сразу двумерный массив, а не перебирающего по ряду (row) цикла?

Вся логика цикла понятна - при присвоении функции $row = mysql_fetch_array($result) производится чтение и увеличение внутри $result на единицу после каждого обращения/присвоения. И каждый раз в цикле переменная $row "затирается".

Но зачем реализовать цикл, если в $result уже сразу вся выборка из базы данных есть и её просто можно было бы присвоить двумерному массиву?

Например:


Код:
$arr2d = array(
           array()
         );

$query = "SELECT Name, CountryCode FROM City WHERE CountryCode = 'NLD' ORDER BY ID DESC"

$result = mysql_query($query);


$arr2d = mysql_fetch_table($result)

echo $arr2d[0]['Name'];  // должно было бы вывести "Alkmaar"
Разработчики PHP не додумались до такой функции?

На мой взгляд, она была бы очень удобна.

Как вы считаете?
76K
20 ноября 2012 года
t3rmin41
14 / / 26.02.2012
Или такая функция есть, но я о ней не знаю?
366
20 ноября 2012 года
int
668 / / 30.03.2005
http://www.php.net/manual/en/function.mysql-result.php
40K
20 ноября 2012 года
D129
228 / / 18.04.2012
Я не ПХП шник, но эта ваша "переменная" ($result = mysql_query($query) - вовсе даже похожа на "датаридер" . А датаридер не содержит всех записей а читает их с сервера по команде, одну за другой и только в одном направлении.
Это довольно низкий уровень взаимодействия с базой, но он же самый быстрый.
76K
20 ноября 2012 года
t3rmin41
14 / / 26.02.2012
Цитата: int
http://www.php.net/manual/en/function.mysql-result.php



Эта функция позволяет обратиться сразу к элементу по порядковому номеру (без цикла), но не извлекает сразу всю выборку в массив. Немного не то. Т.е. чтобы извлечь всю выборку, мне опять-таки надо организовать цикл.

Цитата:
Я не ПХП шник, но эта ваша "переменная" ($result = mysql_query($query) - вовсе даже похожа на "датаридер" . А датаридер не содержит всех записей а читает их с сервера по команде, одну за другой и только в одном направлении.
Это довольно низкий уровень взаимодействия с базой, но он же самый быстрый.



Т.е., другими словами, хотя в коде явно в $result переменную заносится значение один раз:

 
Код:
$result = mysqli_query($link, $query)
на самом деле в $result попадает только первый ряд (row) выборки из базы данных, а потом по мере обращения через
 
Код:
$row = mysqli_fetch_assoc($result)
в $result появляется следующий ряд(row), пока не закрыто соединение с базой данных с помощью mysqli_close($link) ? Я правильно вас понял?

Если так, то этот код должен быть нерабочим:

Код:
<?php
 
 $link = mysqli_connect("localhost","root","root");
 
 mysqli_select_db($link,"world");
 
 $sql = "SELECT * FROM country WHERE Continent = 'Europe'";
 
 $res = mysqli_query($link,$sql); // здесь якобы получили только первый ряд (row)
 
 mysqli_close($link); // здесь закрываем соединение и по идее, не можем больше взаимодействовать с базой данных
 
 echo "<table border='1'>";
 
 while ($row = mysqli_fetch_assoc($res)) // здесь цикл должен бы "прокрутиться" только один раз
 {
   echo "<tr>";
   
   foreach($row as $key => $value)
   {
    echo "<td>".$value."</td>";
   }  
   
   echo "</tr>";
   
 }
 
 echo "</table>";
 
?>
в силу того, что мы сначала выбрали из базы данных то, что нам надо, закрыли соединение с базой данных ( mysqli_close($link) ) и затем организовали цикл обращения к $result-датаридеру. Если каждый раз при присвоении $row = mysqli_fetch_assoc($res) происходило бы чтение из базы данных сервера, то мы бы не могли ничего прочитать после закрытия соединения.

Тем не менее, этот код работает. Значит, в $result появилась сразу вся выборка, не так ли?

Значит, или я не понял вашу мысль, или ваше утверждение неверно. Если я неправильно понял, пожалуйста, потрудитесь яснее описать, что имеете в виду.
Ещё это может быть баг PHP, хотя я так не думаю, так как мой код (где сначала mysqli_close($link), потом цикл) не противоречит логике (по крайней мере той, которую я описал).
40K
21 ноября 2012 года
D129
228 / / 18.04.2012
>>>>> Тем не менее, этот код работает. Значит, в $result появилась сразу вся выборка, не так ли?
Это можно узнать, если разобрать детально реализацию функций. Может быть закрыло, а может быть и проверило - что еще используется и не закрыло, а может быть и кэш какой-нибудь сработал, проверьте ваш код на миллионе записей.....

>>>>> Значит, или я не понял вашу мысль, или ваше утверждение неверно.

- это следует понимать так - " Гарри, сдается мне, что он хочет нас обидеть". :-)
Вы поняли правильно. Но я не писал что утверждаю, а только предполагаю на основании сходства.


>>>>> Ещё это может быть баг PHP, хотя я так не думаю

Вот и правильно. Не стоит искать баги в системе, которую используют миллионы. :-)
Я не пишу на PHP, но из опыта работы с другими системами - могу сказать, что если кажется, что функцию добавили зря, то это только кажется.
Без нее не обойтись, а это значит, что сам обьект, который для вас как бы очевидно что двумерный массив, на самом деле не так уж прост, и не может быть приведен к двумерному массиву автоматически.
40K
21 ноября 2012 года
D129
228 / / 18.04.2012
Думаю, надо начать дискуссию. А там кто-нибудь, кто собаку съел - подтянется и скажет свое веское слово.
:-)
76K
06 декабря 2012 года
t3rmin41
14 / / 26.02.2012
Цитата: D129
Думаю, надо начать дискуссию. А там кто-нибудь, кто собаку съел - подтянется и скажет свое веское слово.
:-)



Вот я и собаку съел, когда почитал про PDO :)

Оказывается, всё это можно сделать, только надо использовать PDO и тогда можно забрать всю выборку одной строкой кода, без всяких циклов. Отобразить, вот, конечно, придётся с циклами (двумя, мы ведь берём двумерный массив - таблицу, матрицу).

Если кому интересно:


Код:
$host = "localhost";
  $user = "root";
  $pass = "root";
  $dbname = "world";
   
  try
  {  
    $dbh = new PDO ("mysql:host=$host;dbname=$dbname",$user,$pass);
   
    $dbh -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  }
  catch (PDOException $e)
  {
   echo $e -> getMessage();
  }  
 
  $data = array ( 'ccode' => 'NLD',
                  'population' => 130000
                  );

  $sql = "SELECT ID, Name, Population
          FROM City
          WHERE CountryCode = :ccode
          AND Population > :population  
          ORDER BY Name ASC"
;
 
  $stmt = $dbh -> prepare($sql);
 
  $stmt -> execute($data);
 
  $stmt -> setFetchMode(PDO::FETCH_ASSOC);
 
  $cities = $stmt-> fetchAll();
  // $cities here - array of arrays, or 2-dimensional array,
  // which we extracted not in a loop, but in one line of code
 
  // view cities START
 
  echo "<table border='1' >";
 
  foreach ($cities as $city) // seek every row <-> city in $cities
  {
    echo "<tr>";
   
    // every $city is an array itself,
    // $city is 1-dimensional array, so we need to extract every column in each row <-> field in each row
   
    foreach ($city as $field)
    {
     echo "<td>".$field."</td>";
    }
   
    echo "</tr>";
   
  }
 
  echo "</table>";
 
  // view cities END
 
  $stmt = null;
 
  $dbh = null;
Или даже так, приближая к нашему первоначальному варианту:

Код:
$host = "localhost";
  $user = "root";
  $pass = "root";
  $dbname = "world";
   
  try
  {  
    $dbh = new PDO ("mysql:host=$host;dbname=$dbname",$user,$pass);
   
    $dbh -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  }
  catch (PDOException $e)
  {
   echo $e -> getMessage();
  }  
 
  $sql = "SELECT ID, Name, Population
          FROM City
          WHERE CountryCode = 'NLD'
          AND Population > 130000  
          ORDER BY Name ASC"
;
 
  $result = $dbh -> query($sql);
 
  $result -> setFetchMode(PDO::FETCH_ASSOC);
 
  $cities = $result -> fetchAll();
  // $cities here - array of 1-dimensional arrays, or 2-dimensional array,
  // which we extracted not in a loop, but in one line of code, which is to my mind more efficient
 
  // view cities START
 
  echo "<table border='1' >";
 
  foreach ($cities as $city) // seek every row <-> city in $cities
  {
    echo "<tr>";
   
    // every $city is an array itself,
    // $city is 1-dimensional array, so we need to extract every column in each row <-> field in each row
   
    foreach ($city as $field)
    {
     echo "<td>".$field."</td>";
    }
   
    echo "</tr>";
   
  }
 
  echo "</table>";
 
 
  // view cities END
 
  $result = null;
 
  $dbh = null;
Так что, в $result = mysql_fetch_assoc($query) после обращения к базе данных с самого начала находится вся выборка.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог