Toffiak blog

PDO tutorial

W tym tutorialu przedstawię wam czym jest PDO i jak należy z niego korzystać, zabaczycie także do czego można wykorzystać zapytania przygotowane oraz jak formatować otrzymane dane.

Wstęp

Wszystkie przykłady wykorzystują bazę danych MySQL w wersji 5.5, z tego względu nie wszystko będzie tak samo działać na innych silnikach bazy danych i vice versa ( np: \PDO::FETCH_ORI_PREV ).

Czym jest PDO i dlaczego należy je stosować ?

PDO jest rozszerzeniem języka PHP udostępniającym uniwersalny interejs do komunikacji z bazami danych. PDO udostępnia tylko interfejs, samą komunikacją zajmują się natomiast odpowiednie sterowniki. Oznacza to że gdy zechcemy zmienić silnik bazy danych np: z MySQL na PostgreSQL to cała zmiana ogranicza się do zmiany sterownika, nasze zapytania wciąż będą działać. W dawnych czasach dla każdego z tych silników musieliśmy używać innego zestawu funkcji, przy zmianie silnika musielibyśmy je także odpowiednio zmienić. PDO jest dostępny od wersji PHP 5.1 więc o ile nie korzystamy z jakiejś archaicznej wersji PHP to mamy do niego dostęp.
Dlaczego powinniśmy stosować PDO ?

  • czytelny obiektowy kod z obsługą błędów
  • dostęp do tych samych metod niezależnie od używanego silnika bazy danych
  • rozszerzenie mysql jest oznaczone jako przestarzałe dla PHP 5.5 i zostanie usunięte w jednej z kolejnych wersji

Wykorzystywana baza danych

Schemat bazy

Tabela "actor"
idfirstnamelastnameagecountry_id
1TomCruse512
1AntonioBanderas536
3SandraBullock492
4KeiraKnightley283
5CezaryPazura511
Tabela "film"
idname
1Speed
1Desperado
3Psy
4World War Z
5Mission Impossible
6Człowiek demolka
7Rozważna i romantyczba
8Piraci z karaibów i romantyczba
Tabela "country"
idname
1Poland
1USA
3UK
4Germany
5France
6Spain
7Jamaica
Tabela "actor_film"
actor_idcountry_id
31
22
53
14
15
36
47
48

Połączenie z bazą danych i pierwsze zapytanie

        <?php

        try {
            $dbh = new \PDO('mysql:host=localhost;dbname=pdoartykul', 'username', 'password', array());    
        } catch (PDOException $e) {
            print $e;
        }
    

Konstruktor klasy PDO przyjmuje 4 argumenty: pierwszy to DSN, drugi nazwę uzytkownika bazy danych, trzeci hasło użytkownika natomiast czwarty dodatkowe opcję połączenia.
W zależności od użytgo sterownika, DSN może się różnić formatem, szczegóły w oficjalnej dokumentacji http://www.php.net/manual/en/pdo.drivers.php
O ile nie otrzymaliśmy żadnych błędów to możemy przejść dalej, jeśli nie to:

  • należy sprawdzić dokładnie czy poprawnie wpisane zostały: użytkownik i hasło do bazy danych
  • port na którym nasłuchuje MySQL, domyślnie jest to 3306

Mając poprawnie skonfigurowane połączenie wybierzemy wszystkich aktorów którzy są starsi niż 52 lata

        <?php

        try {
            $dbh = new \PDO('mysql:host=localhost;dbname=pdoartykul', 'username', 'password', array());

            // Wybieranie aktorów w wieku 52+
            $age = 52;
            foreach ($dbh->query('SELECT * FROM actor a WHERE a.age > ' . $age) as $row) {
                print_r($row);
            }
        } catch (PDOException $e) {
            print $e;
        }
    
        Array
        (
            [id] => 2
            [0] => 2
            [firstname] => Antonio
            [1] => Antonio
            [lastname] => Banderas
            [2] => Banderas
            [age] => 53
            [3] => 53
            [country_id] => 6
            [4] => 6
        )
    

W naszym skrypcie korzystamy z metody query służy ona do przygotowania zapytania i wykonania go, wynikiem jej działania jest tabela z aktorami którzy są starsi niż 52 lata, jak widać jest tylko jeden taki aktor.

Przygotowane zapytania ( prepared statements )

W przykładzie powyżej pobraliśmy wszystkich aktorów z wiekiem większym niż 52 lata, załóżmy że mamy tablicę dostępnych lat dla których będziemy pobierać aktorów i wyświetlać ich. Możemy za każdym razem budować osobne zapytanie i wykonywać je dla każdego wieku, jest jednak lepszy sposób: zapytania przygotowane.
Tworzenie zapytania i jego wykonanie jest stosunkowo kosztowne, cały proce składa się z wielu kroków w których każde zapytanie jest analizowane kompilowane i optymalizowane w celu jak najszybszego wykonania, zapytania przygotowane zmniejszają ilość kroków, zapytanie jest tworzone raz a może być wykorzystane dla różnych parameterów. Zapytania przygotowane można wyobrazić sobie jako szablony w których niektóre częsci są dynamiczne uzupełniane, w naszym przypadku dynamiczny będzie wiek.

        <?php

        try {
            $dbh = new \PDO('mysql:host=localhost;dbname=pdoartykul', 'username', 'password', array());

            $ages = array(51, 53);
            $stmt = $dbh->prepare('SELECT * FROM actor a WHERE a.age = :age');
            foreach ($ages as $age) {
                $stmt->bindParam(':age', $age, \PDO::PARAM_INT);
                $stmt->execute();
                print_r($stmt->fetchAll());
            }
        } catch (PDOException $e) {
            print $e;
        }
    
        Array
        (
            [0] => Array
                (
                    [id] => 1
                    [0] => 1
                    [firstname] => Tom
                    [1] => Tom
                    [lastname] => Cruse
                    [2] => Cruse
                    [age] => 51
                    [3] => 51
                    [country_id] => 2
                    [4] => 2
                )

            [1] => Array
                (
                    [id] => 5
                    [0] => 5
                    [firstname] => Cezary
                    [1] => Cezary
                    [lastname] => Pazura
                    [2] => Pazura
                    [age] => 51
                    [3] => 51
                    [country_id] => 1
                    [4] => 1
                )

        )
        Array
        (
            [0] => Array
                (
                    [id] => 2
                    [0] => 2
                    [firstname] => Antonio
                    [1] => Antonio
                    [lastname] => Banderas
                    [2] => Banderas
                    [age] => 53
                    [3] => 53
                    [country_id] => 6
                    [4] => 6
                )

        )
    

Nasze parametry przypisujemy do zapytania ( bindujemy ) w pętli za pomocą metody bindParam, metoda ta przyjmuje 5 parameterów: idetyfikator parameteru, zmienną PHP zawierającą podstawiany parameter, typ parameteru, długość typu parameteru oraz opcję sterownika. Tylko dwa pierwsze są wymagane, jednak często podaje się także typ parametru, w przypadku jego nie podania przyjmuje on domyślną wartość: \PDO::PARAM_STR.

Parametry zapytania można podawać w dwóch formatach: jako parameter nazwany lub jako znak zapytania, poniżesze przykłady zwrócą ten sam wynik.

        <?php

        try {
            $dbh = new \PDO('mysql:host=localhost;dbname=pdoartykul', 'username', 'password', array());

            $actorFirstname = "Tom";
            $actorLastname = "Cruse";

            // Przygotowane zapytanie z parameterem nazwanym
            $stmt = $dbh->prepare('SELECT f.name FROM film f LEFT JOIN actor_film af ON f.id = af.film_id LEFT JOIN actor a ON af.actor_id = a.id WHERE a.firstname = :firstname AND a.lastname = :lastname');
            $stmt->bindParam(':firstname', $actorFirstname, \PDO::PARAM_STR);
            $stmt->bindParam(':lastname', $actorLastname, \PDO::PARAM_STR);
            $stmt->execute();
            var_dump($stmt->fetchAll());

            // Przygotowane zapytanie ze znakiem zapytania
            $stmt = $dbh->prepare('SELECT f.name FROM film f LEFT JOIN actor_film af ON f.id = af.film_id LEFT JOIN actor a ON af.actor_id = a.id WHERE a.firstname = ? AND a.lastname = ?');
            $stmt->bindParam(1, $actorFirstname, \PDO::PARAM_STR);
            $stmt->bindParam(2, $actorLastname, \PDO::PARAM_STR);
            $stmt->execute();
            var_dump($stmt->fetchAll());
        } catch (PDOException $e) {
            print $e;
        }
    
        array(2) {
            [0]=>
                array(2) {
                    ["name"]=>
                    string(11) "World War Z"
                    [0]=>
                    string(11) "World War Z"
                }
            [1]=>
                array(2) {
                    ["name"]=>
                    string(18) "Mission Impossible"
                    [0]=>
                    string(18) "Mission Impossible"
                }
            }
        array(2) {
            [0]=>
                array(2) {
                    ["name"]=>
                    string(11) "World War Z"
                    [0]=>
                    string(11) "World War Z"
                }
            [1]=>
                array(2) {
                    ["name"]=>
                    string(18) "Mission Impossible"
                    [0]=>
                    string(18) "Mission Impossible"
            }
        }
    

bindValue

W poprzednim przykładach korzystaliśmy z metody bindParam w której nasz parameter przekazywaliśmy jako zmienną, można jednak bezpośrednio podawać parameter bez tworzenia zmiennej do tego służy właśnie metoda bindValue.

Format zwracanych danych

We wszystkich poprzednich przykładach korzystaliśmy z domyślnego sposobu wyświetlania danych: \PDO::FETCH_BOTH, istnieją też inne które wykorzystwane są częściej.

\PDO::FETCH_ASSOC

Zwraca rekordy w postaci tablicy asocjacyjnej w której kluczami są nazwy kolumn.

        <?php

        try {
            $dbh = new \PDO('mysql:host=localhost;dbname=pdoartykul', 'username', 'password', array());

            $stmt = $dbh->prepare('SELECT * FROM country c WHERE c.name  like :name');
            $stmt->bindValue(':name', 'U%');
            $stmt->execute();
            while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
                var_dump($row);
            }
            $stmt->closeCursor();
        } catch (PDOException $e) {
            print $e;
        }
    
        array(2) {
            ["id"]=>
            string(1) "2"
            ["name"]=>
            string(3) "USA"
        }
        array(2) {
            ["id"]=>
            string(1) "3"
            ["name"]=>
            string(2) "UK"
        }
    

\PDO::FETCH_BOUND

Przypisuje wybrane kolumny do wybranych zmiennych PHP.

        <?php

        try {
            $dbh = new \PDO('mysql:host=localhost;dbname=pdoartykul', 'username', 'password', array());

            $stmt = $dbh->prepare('SELECT * FROM country c WHERE c.name  like :name');
            $stmt->bindValue(':name', 'U%'); 
            $countryId = null;
            $countryName = null;
            $stmt->bindColumn('id', $countryId);
            $stmt->bindColumn('name', $countryName);
            $stmt->execute();
            while ($row = $stmt->fetch(\PDO::FETCH_BOUND)) {
                print $countryId.' '.$countryName. PHP_EOL;
            }
            $stmt->closeCursor();
        } catch (PDOException $e) {
            print $e;
        }
    
        2 USA
        3 UK
    

\PDO::FETCH_CLASS

Przypisuje pobrane wartości jako właściwości wybranej klasy. W przykładzie poniżej utworzyliśmy klasę "Country" która posiada właściwości: name, id.
PDO pobiera kolejne wyznaczone wiersze, tworzy obiekty klasy Country i wypełnia je pobranymi danymi.

        <?php

        class Country
        {

            public $name;
            public $id;

        }

        try {
            $dbh = new \PDO('mysql:host=localhost;dbname=pdoartykul', 'username', 'password', array());

            $stmt = $dbh->prepare('SELECT * FROM country c WHERE c.name  like :name');
            $stmt->bindValue(':name', 'U%');
            $stmt->execute();

            foreach ($stmt->fetchAll(\PDO::FETCH_CLASS, 'Country') as $country) {
                print 'Country id: '.$country->id. PHP_EOL;
                print 'Country name: '.$country->name. PHP_EOL;
                var_dump($country);
            }
        } catch (PDOException $e) {
            print $e;
        }
    
        Country id: 2
        Country name: USA
        object(Country)#3 (2) {
            ["name"]=>
            string(3) "USA"
            ["id"]=>
            string(1) "2"
        }
        Country id: 3
        Country name: UK
        object(Country)#4 (2) {
            ["name"]=>
            string(2) "UK"
            ["id"]=>
            string(1) "3"
        }
    

\PDO::FETCH_LAZY

Podobnie jak \PDO::FETCH_CLASS tworzy obiekt i wypełnia go wyznaczonymi danymi, tym razem jednak nie tworzymy własnej klasy a otrzymane obiekty są obiektami klasy PDORow.

        <?php        

        try {
            $dbh = new \PDO('mysql:host=localhost;dbname=pdoartykul', 'username', 'password', array());

            $stmt = $dbh->prepare('SELECT * FROM country c WHERE c.name  like :name');
            $stmt->bindValue(':name', 'U%');
            $stmt->execute();
            while($row = $stmt->fetch(\PDO::FETCH_LAZY)){
                print \get_class($row). PHP_EOL;
                var_dump($row);
            }
            $stmt->closeCursor();
        } catch (PDOException $e) {
            print $e;
        }
    
        PDORow
        object(PDORow)#3 (3) {
            ["queryString"]=>
            string(48) "SELECT * FROM country c WHERE c.name  like :name"
            ["id"]=>
            string(1) "2"
            ["name"]=>
            string(3) "USA"
        }
        PDORow
        object(PDORow)#3 (3) {
            ["queryString"]=>
            string(48) "SELECT * FROM country c WHERE c.name  like :name"
            ["id"]=>
            string(1) "3"
            ["name"]=>
            string(2) "UK"
        }
    

\PDO::FETCH_COLUMN

Zwraca tylko wybraną kolumnę w każdym rekordzie, wybraną kolumnę podajemy jak wartość liczbową. Pierwsza kolumna ma index 0.
W naszym przypadku pobieramy tylko nazwy krajów, nazwa kraju jest naszą drugą kolumną w tabeli czyli jej index to 1.

        <?php        

        try {
            $dbh = new \PDO('mysql:host=localhost;dbname=pdoartykul', 'username', 'password', array());

            $stmt = $dbh->prepare('SELECT * FROM country c WHERE c.name  like :name');
            $stmt->bindValue(':name', 'U%');
            $stmt->execute();
            foreach ($stmt->fetchAll(\PDO::FETCH_COLUMN, 1) as $row) {
                print $row . PHP_EOL;
            }
        } catch (PDOException $e) {
            print $e;
        }
    
        USA
        UK
    

\PDO::FETCH_FUNC

Pozwala na manipulowanie danymi poprzez ich przekazywanie do wybranej funkcji.

        <?php        

        try {
            $dbh = new \PDO('mysql:host=localhost;dbname=pdoartykul', 'username', 'password', array());

            function lower($id, $name)
            {
                return $id . ' ' . \mb_strtolower($name);
            }

            $stmt = $dbh->prepare('SELECT * FROM country c WHERE c.name  like :name');
            $stmt->bindValue(':name', 'U%');
            $stmt->execute();
            $data = $stmt->fetchAll(\PDO::FETCH_FUNC, 'lower');
            var_dump($data);
        } catch (PDOException $e) {
            print $e;
        }
    
        array(2) {
              [0]=>
              string(5) "2 usa"
              [1]=>
              string(4) "3 uk"
        }
    

\PDO::FETCH_GROUP

Grupuje wyniki po wybranej wartości. // Zmienić

        <?php        

        try {
            $dbh = new \PDO('mysql:host=localhost;dbname=pdoartykul', 'username', 'password', array());

            $stmt = $dbh->prepare('SELECT * FROM country c WHERE c.name  like :name');
            $stmt->bindValue(':name', 'U%');
            $stmt->execute();
            var_dump($stmt->fetchAll(\PDO::FETCH_GROUP|\PDO::FETCH_COLUMN,1));
        } catch (PDOException $e) {
            print $e;
        }
    
        array(2) {
            ["USA"]=>
            array(1) {
                [0]=>
                string(1) "2"
            }
            ["UK"]=>
            array(1) {
                [0]=>
                string(1) "3"
            }
        }
    

\PDO::FETCH_INTO

Aktualizuje właściwości podanego obiektu.

        <?php        

        try {
            $dbh = new \PDO('mysql:host=localhost;dbname=pdoartykul', 'username', 'password', array());

            class Country
            {

                public $id;
                public $name;
                public $code = 'PL/POL';

                public function __construct($id, $countryName)
                {
                    $this->id = $id;
                    $this->name = $countryName;
                }

            }

            $randomCountry = new Country(null, 'Czech Republic');
            $stmt = $dbh->prepare('SELECT * FROM country c WHERE c.name  like :name');
            $stmt->bindValue(':name', 'U%');
            $stmt->execute();
            $stmt->setFetchMode(\PDO::FETCH_INTO, $randomCountry);
            while ($row = $stmt->fetch()) {
                var_dump($randomCountry);
            }
            $stmt->closeCursor();
        } catch (PDOException $e) {
            print $e;
        }
    
        object(Country)#2 (4) {
              ["is"]=>
              NULL
              ["name"]=>
              string(3) "USA"
              ["code"]=>
              string(6) "PL/POL"
              ["id"]=>
              string(1) "2"
        }
        object(Country)#2 (4) {
              ["is"]=>
              NULL
              ["name"]=>
              string(2) "UK"
              ["code"]=>
              string(6) "PL/POL"
              ["id"]=>
              string(1) "3"
        }
    

\PDO::FETCH_KEY_PAIR

Zwraca wyznaczone rekordy w postaci pary: klucz => wartość, kluczem jest wyznaczona wartość pierwszej kolumny a wartością druga kolumna.
Należy użyć dokładnie dwóch kolumn inna wartość spowoduje błąd.

        <?php        

        try {
            $dbh = new \PDO('mysql:host=localhost;dbname=pdoartykul', 'username', 'password', array());

            $stmt = $dbh->prepare('SELECT name,id FROM country c WHERE c.name  like :name');
            $stmt->bindValue(':name', 'U%');
            $stmt->execute();
            while ($row = $stmt->fetch(\PDO::FETCH_KEY_PAIR)) {
                var_dump($row);
            }
            $stmt->closeCursor();
        } catch (PDOException $e) {
            print $e;
        }
    
        array(1) {
            ["USA"]=>
            string(1) "2"
        }
        array(1) {
            ["UK"]=>
            string(1) "3"
        }
    

\PDO::FETCH_NAMED

Każdy znaleziony rekord jest zwracany jako tablica asocjacyjna w której kluczem jest nazwa kolumny.

        <?php        

        try {
            $dbh = new \PDO('mysql:host=localhost;dbname=pdoartykul', 'username', 'password', array());

            $stmt = $dbh->prepare('SELECT * FROM country c WHERE c.name  like :name');
            $stmt->bindValue(':name', 'U%');
            $stmt->execute();
            while ($row = $stmt->fetch(\PDO::FETCH_NAMED)) {
                var_dump($row);
            }
            $stmt->closeCursor();
        } catch (PDOException $e) {
            print $e;
        }
    
        array(2) {
            ["id"]=>
            string(1) "2"
            ["name"]=>
            string(3) "USA"
        }
            array(2) {
            ["id"]=>
            string(1) "3"
            ["name"]=>
            string(2) "UK"
        }
    

\PDO::FETCH_NUM

Podobnie jak wyżej tylko że kluczami są numery kolumn.

        <?php        

        try {
            $dbh = new \PDO('mysql:host=localhost;dbname=pdoartykul', 'username', 'password', array());

            $stmt = $dbh->prepare('SELECT * FROM country c WHERE c.name  like :name');
            $stmt->bindValue(':name', 'U%');
            $stmt->execute();
            while ($row = $stmt->fetch(\PDO::FETCH_NUM)) {
                var_dump($row);
            }
            $stmt->closeCursor();
        } catch (PDOException $e) {
            print $e;
        }
    
        array(2) {
            [0]=>
            string(1) "2"
            [1]=>
            string(3) "USA"
        }
        array(2) {
            [0]=>
            string(1) "3"
            [1]=>
            string(2) "UK"
        }
    

\PDO::FETCH_OBJ

Zwraca rekordy w postaci obiektów klasy stdClass.

        <?php        

        try {
            $dbh = new \PDO('mysql:host=localhost;dbname=pdoartykul', 'username', 'password', array());

            $stmt = $dbh->prepare('SELECT * FROM country c WHERE c.name  like :name');
            $stmt->bindValue(':name', 'U%');
            $stmt->execute();
            while ($obj = $stmt->fetch(\PDO::FETCH_OBJ)) {
                var_dump($obj);
            }
            $stmt->closeCursor();
        } catch (PDOException $e) {
            print $e;
        }
    
        object(stdClass)#3 (2) {
            ["id"]=>
            string(1) "2"
            ["name"]=>
            string(3) "USA"
        }
        object(stdClass)#4 (2) {
            ["id"]=>
            string(1) "3"
            ["name"]=>
            string(2) "UK"
        }
    

\PDO::FETCH_PROPS_LATE

Pozwala na przekazanie dodatkowych parameterów do kontruktora przed przypisaniem właściwości.

        <?php        

        class Country
        {

            private $name;
            private $id;
            private $code;
            private $location;

            public function __construct($countryCode, $location)
            {
                $this->code = $countryCode;
                $this->location = $location;
            }

        }

        try {
            $dbh = new \PDO('mysql:host=localhost;dbname=pdoartykul', 'username', 'password', array());

            $stmt = $dbh->prepare('SELECT * FROM country c WHERE c.name  like :name');
            $stmt->bindValue(':name', 'U%');
            $stmt->execute();
            foreach ($stmt->fetchAll(\PDO::FETCH_CLASS | \PDO::FETCH_PROPS_LATE, 'Country', array('countryCode' => 'PL/POL', 'location' => 'Europe')) as $country) {
                var_dump($country);
            }
        } catch (PDOException $e) {
            print $e;
        }
    
        object(Country)#3 (4) {
            ["name":"Country":private]=>
            string(3) "USA"
            ["id":"Country":private]=>
            string(1) "2"
            ["code":"Country":private]=>
            string(6) "PL/POL"
            ["location":"Country":private]=>
            string(6) "Europe"
        }
            object(Country)#4 (4) {
            ["name":"Country":private]=>
            string(2) "UK"
            ["id":"Country":private]=>
            string(1) "3"
            ["code":"Country":private]=>
            string(6) "PL/POL"
            ["location":"Country":private]=>
            string(6) "Europe"
        }
    

\PDO::FETCH_ORI_ABS, \PDO::FETCH_ORI_FIRST, \PDO::FETCH_ORI_LAST, \PDO::FETCH_ORI_NEXT, \PDO::FETCH_ORI_PRIOR, \PDO::FETCH_ORI_REL

Pozwala na dowolne przemieszcznie się w wyznaczonych wynikach.

  • \PDO::FETCH_ORI_ABS - pozwala na wybór rekordu na podstawie jego numeru
  • \PDO::FETCH_ORI_FIRST - pobiera pierwszy rekord
  • \PDO::FETCH_ORI_LAST - pobiera ostatni rekord
  • \PDO::FETCH_ORI_NEXT - pobiera następny rekord
  • \PDO::FETCH_ORI_PRIOR - pobiera poprzedni rekord
  • \PDO::FETCH_ORI_REL - pobiera rekord relatywny w stosunku do aktulnego położenia kursora

W tym przykładzie nie ma pokazanych wyników dla skryptu, a to dlatego że MySQL nie obługuje dowolnego przemieszczania się po wyznaczonych wynikach, kursor będzie przesuwał się od pierwszego do ostatniego wyznaczonego rekordu.

        <?php        

        try {
            $dbh = new \PDO('mysql:host=localhost;dbname=pdoartykul', 'username', 'password', array());

            $stmt = $dbh->prepare('SELECT * FROM country c');
            $stmt->execute();

            // Pobieranie rekordu na podstawie numeru
            $rowByNumber = $stmt->fetch(\PDO::FETCH_ORI_ABS, 3);
            var_dump($rowByNumber);

            // Pobieranie pierwszego rekordu
            $firstRow = $stmt->fetch(\PDO::FETCH_ORI_FIRST);
            var_dump($firstRow);

            // Pobieranie ostatniego rekordu
            $lastRow = $stmt->fetch(\PDO::FETCH_ORI_LAST);
            var_dump($lastRow);

            // Pobieranie następnego rekordu
            $nextRow = $stmt->fetch(\PDO::FETCH_ORI_NEXT);
            var_dump($nextRow);

            // Pobieranie poprzedniego rekordu
            $previousRow = $stmt->fetch(\PDO::FETCH_ORI_PRIOR);
            var_dump($previousRow);

            // Pobieranie relatywnego rekordu
            $relativeRow = $stmt->fetch(\PDO::FETCH_ORI_REL);
            var_dump($relativeRowRow);

            $stmt->closeCursor();
        } catch (PDOException $e) {
            print $e;
        }
    

Komentarze

blog comments powered by Disqus