W ramach eksperymentu "co można wycisnąć z magicznych funkcji PHP" postanowiłem sprawdzić, na ile można ułatwić sobie pobieranie/aktualizowanie jednej konkretnej wartości z bazy danych.
Założenia były takie:
- istnieje klasa db, która jest odpowiedzialna za komunikację z RDBS
- pobrać można wartość tylko jednego pola z jednego rekordu
- wybór rekordu odbywa się przez podanie wartości pola id
- pobranie/aktualizowanie wartości musi być możliwie proste
Udało mi się uzyskać efekt, pozwalający pobrać wartość takim zapisem:
$iAge = $db -> contact[17] -> age;
Aktualizacja wartości to z kolei:
$db -> contact[17] -> age = 18;
Przy czym:
- $db - to już istniejący obiekt zapewniający dostęp do bazy
- contact - nazwa tablicy w bazie
- 17 - wartość pola id
- age - nazwa pola pobieranego/aktualizowanego
Jak to uzyskałem?
Tytułem wstępu:
- magiczna metoda __get() w klasie pozwala obsłużyć sytuację, w której użytkownik obiektu próbuje pobrać wartość nie istniejącej składowej (lub składowej nie będącej publiczną). W takim przypadku zostanie wykonana metoda __get() - jako parametr otrzyma nazwę składowej. Jej wynik zostanie zwrócony jako wartość składowej
- magiczna metoda __set() w klasie działa podobnie - pozwala ustawić wartość niedostępnej składowej. Otrzymuje dwa parametry - nazwę i nową wartość składowej
- interfejs ArrayAccess pozwala obsłużyć sytuację, w której obiekt jest traktowany jak tablica. Metoda offsetGet() jest wywoływana w momencie, kiedy użytkownik obiektu próbuje pobrać konkretny element tablicy
A teraz - jak to działa?
- magiczna funkcja __get() w klasie db, zwraca obiekt klasy magdb_table, przekazując do konstruktora nazwę pobieranej składowej (czyli nazwę tabeli) oraz obiekt tej klasy na którym wywołano metodę (czyli $this)
- klasa magdb_table implementuje interfejs ArrayAccess - pozwala nam to "przejąć" indeks będący potrzebny do określenia rekordu, z którego pobieramy dane. Metoda offsetGet() zwraca obiekt klasy magdb_row, przekazując do jego konstruktora niezbędne informacje: obiekt $db, nazwę tablicy (to otrzymaliśmy w konstruktorze) oraz indeks - ten metoda otrzymała w parametrach wywołania
- na koniec zostajemy z obiektem klasy magdb_row. Otrzymał on w konstruktorze: obiekt $db (pozwalający na dostęp do bazy), nazwę tabeli z której pobieramy dane (ew. aktualizujemy), id wiersza (to jest uproszczenie - dokładnie rzecz ujmując, otrzymaliśmy wartość której możemy użyć w klauzuli where, zakładając, że kolumna ID ma unikalne wartości). Ostatnią rzeczą która pozostała do zrobienia, to użycie metod __get() i __set() do pobrania/zaktualizowania danych w bazie. Metoda __get() otrzymuje nazwę zmiennej (czyli nazwę pola) a metoda __set() dodatkowo nową wartość
Poniżej - kod. Wyjęty z istniejącego projektu i "oczyszczony" ze wszystkiego, co nie stanowi meritum sprawy. Działający w oryginale - ten poniżej nie testowany. Przed użyciem trzeba dodać oczywiście kontrolę błędów, kontrolę wartości (szczególnie indeksu), no i oczywiście samo pobieranie/aktualizowanie danych.
Co dalej? To był tylko eksperyment, ale w ramach jego kontynuacji można by:
- obsłużyć offsetUnset() w magdb_table - pozwalając na usuwanie rekordów
- obsłużyć offsetSet() w magdb_table - pozwalając na tworzenie rekordów (lub aktualizację kilku wartości za jednym zamachem) przez podanie tablicy asocjacyjnej
class db{
public function __get($name){
return new magdb_table($name, $this);
}
}
class magdb_table implements ArrayAccess{
private $name;
private $db;
public function __construct($sName, $db){
$this -> name = $sName;
$this -> db = $db;
}
public function offsetExists($offset){}
public function offsetUnset($offset){}
public function offsetSet($offset, $value) {}
public function offsetGet($offset) {
return new magdb_row($this -> name, $offset, $this -> db);
}
}
class magdb_row{
private $table;
private $rowId;
private $db;
public function __construct($sTable, $iRowId, $db){
$this -> db = $db;
$this -> table = $sTable;
$this -> rowId = $iRowId;
}
public function __get($sName){
// sql goes here
// select $sName from $this -> table where id = $this -> rowId
// $sName - column name
// $this -> table - table name
// $this -> rowId - id value
}
public function __set($sName, $sValue){
// sql goes here
// update $this -> table set $sName where id = $this -> rowId
// $sName - column name
// $this -> table - table name
// $this -> rowId - id value
}
}
Cieszę się że wróciłeś do pisania
ReplyDeleteI am not sure where you are getting your
ReplyDeleteinfo, but great topic. I needs to spend some
time learning more or understanding more. Thanks for
great information I was looking for this info for my mission.
What Is Betfair Paywall? - WorkMaker Money
ReplyDeleteBetfair is a betting 온카지노 exchange and bookmaker. It 1xbet korean is a popular online bookmaker for Australian punters and หารายได้เสริม online punters. It offers a wide range of