• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Problem z obiektowym łączeniem z bazą danych

Cloud VPS
0 głosów
455 wizyt
pytanie zadane 11 sierpnia 2020 w PHP przez Bakkit Dyskutant (7,600 p.)

Witam, zaczynam przygodę z obiektowym php'em. Napisałem sobie kod na dodawaniem danych do bazy:

class Base {
        public $db_config = array(
            'host' => 'localhost',
            'port' => '3306',
            'user' => 'root',
            'pass' => '',
            'db' => 'oop',
            'db_type' => 'mysql',
            'encoding' => 'utf-8'
        );

        public $options = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);

        // Connect to Database
        public function __construct() {
            try {
                $dsn = $this->db_config['db_type'] . ':host=' . $this->db_config['host'] . ';port=' . $this->db_config['port'] . ';encoding=' . $this->db_config['encoding'] . ';dbname=' . $this->db_config['db'];
                
                $conn = new PDO($dsn, $this->db_config['user'], $this->db_config['pass'], $this->options);

            } catch(PDOException $e) {
                die('Nie można połączyć z bazą danych: '.$e->getMessage().'</br>'); 
            }
        }
    }

    class Base_add extends Base {
        public function add($table, $val1, $val2) {
            $result = $conn->prepare("INSERT INTO '$table' VALUES null '$val1', '$val2'");
            $result->execute();
            $row = $result->fetch();
        }
    }


W dalszej części kodu oczywiście obiekt jest wywoływany, natomiast nie wczytuje mi zmiennej $conn. Tutaj wyświetlany błąd:

Notice: Undefined variable: conn in C:\xampp\htdocs\... on line 30

 

Proszę o pomoc oraz nakierowanie na rozwiązanie problemu. Możecie też doradzić czy robię to w dobry sposób? Mój pierwszy raz z obiektówką.

1 odpowiedź

+1 głos
odpowiedź 11 sierpnia 2020 przez Arkadiusz Waluk Ekspert (290,310 p.)
wybrane 12 sierpnia 2020 przez Bakkit
 
Najlepsza
$result = $conn->prepare("INSERT INTO '$table' VALUES null '$val1', '$val2'");

Używasz tu $conn, a taka zmienna nie jest zadeklarowana w metodzie add(). Masz ją jako właściwość w klasie, więc pewnie chodziło Ci o $this->conn.

Jeśli chodzi o ogólne porady to nie umieszczałbym konfiguracji połączenia w klasie. Chyba że to jakieś domyślnie tylko, ale i tak raczej średnio. Jak będzie trzeba zmieniać konfigurację aplikacji, to szukanie wielu klas i gdzie co jest zadeklarowane, jest mega niewygodne. Unikałbym raczej przerywania kodu przez die() gdzieś w niewiadomym miejscu, raczej rzucał wyjątki i obsługiwał je w jednym miejscu. Zamiast array() można śmiało użyć [], array() to starszy zapis. Twoja metoda add() jest dość ograniczająca, nie można nawet podać listy pól do zmiany, a samych wartości do bazy nie wstawiamy po prostu do stringa, tylko bindujemy (bindParam()/bindValue()). Nie przestrzegasz też PSR-2/12 - to są style wyglądu kodu, nieoficjalne i nieobowiązkowe oczywiście, ale bardzo popularne w PHP (to sposób nazewnictwa, zapisu klamer itd.). Na ten moment szczerze mówiąc to w ogóle nie wiem czy ta klasa ma sens, bo nie robi nic specjalnego poza wywołaniem metod PDO, ale może to jeszcze rozwiniesz.

komentarz 11 sierpnia 2020 przez Bakkit Dyskutant (7,600 p.)

Tak, oczywiście wszystko będę rozwijał.

Metodę add zmieniłem na:

class Base_add extends Base {
        public function add($q) {
            $result = $this->conn->prepare($q);
            $result->execute();
        }
    }

co myślę, że ma troszkę większy sens. Tylko gdzie mam teraz wpleść bindowanie?

Mógłbym jeszcze prosić o  jakiś odnośnik dot. obsługiwania wyjątków?

1
komentarz 11 sierpnia 2020 przez Arkadiusz Waluk Ekspert (290,310 p.)
No właśnie, dlatego sam widzisz, że masz teraz metodę na 2 proste linijki, która jednocześnie ogranicza Ci wywołanie innych rzeczy. Jak chcesz w taki sposób to możesz próbować np. przekazać kolejny argument - tablicę wartości do bindowania w rodzaju klucz z zapytania => wartość i odpowiednio to obsłużyć w metodzie i zamienić na bindowanie.

Obsługiwania wyjątków tzn. czysto w kodzie jak to się robi? Tak jak już teraz obsługujesz, tylko że tu od razu zabijasz skrypt. Pomyślałbym po prostu czy nie zrobić jednego uniwersalnego miejsca w aplikacji, które będzie łapało wszystkie (albo większość, czasem mogą być wykluczenia z reguły) wyjątki i decydowało co z nimi zrobić. Przykładowo, wyobraź sobie, że chcesz wysłać sobie powiadomienie o błędzie albo zalogować jego szczegóły. Jeśli w 50 miejscach będziesz miał obsługę błędów przez die(), to będziesz musiał każde to miejsce znaleźć i tam 50 razy dodać to samo. Zamiast otworzyć 1 miejsce i tam dodać obsługę.
komentarz 12 sierpnia 2020 przez Bakkit Dyskutant (7,600 p.)

Ok, dzięki. Jeszcze chciałem zapytać czy taka funkcja mogła by zastąpić bindowanie:

private function clear($string){
    return htmlentities($string, ENT_QUOTES, 'UTF-8');
    }
komentarz 12 sierpnia 2020 przez Arkadiusz Waluk Ekspert (290,310 p.)
Nie, htmlentities() możesz użyć dodatkowo jeśli potrzebujesz się zabezpieczyć np. przed tym, aby ktoś nie wstrzyknął kodu HTML/JS na stronę. Do zabezpieczenia przed sql injection używamy bindowania, gdzie samo zapytanie do bazy idzie osobno i wartości osobno, więc nie ma wtedy możliwości przeprowadzenia ataku.

Podobne pytania

0 głosów
0 odpowiedzi 361 wizyt
pytanie zadane 30 sierpnia 2020 w PHP przez Bakkit Dyskutant (7,600 p.)
0 głosów
3 odpowiedzi 618 wizyt
pytanie zadane 25 października 2015 w PHP przez babiak Obywatel (1,810 p.)
0 głosów
1 odpowiedź 1,499 wizyt
pytanie zadane 6 czerwca 2017 w PHP przez To Ja Początkujący (490 p.)

93,464 zapytań

142,459 odpowiedzi

322,730 komentarzy

62,844 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Kursy INF.02 i INF.03
...