Categories
Работа Статии

Статични данни, PHP, урок 2

Ситуацията е следната – имам няколко обекта, които онаследяват някакъв клас. В родителският клас има методи, които връщат определени суми. При първоначалният ми план, бях направил всеки метод ( три метода ) да си определя сумата с отделна заявка – т.е. три заявки на обект умножени по четири класа т.е. заявките към базата стават дванадесет. Ето примера:

class A {

public function A1() {
// DB Query
}
public function A2() {
// DB Query
}
public function A3() {
// DB Query
}
}

class B extends A {

public function B() {
parent::__construct(); // Задавам нови насройки на базата
}
}

class C extends A {

public function B() {
parent::__construct(); // Задавам нови насройки на базата
}
}

class D extends A {

public function B() {
parent::__construct(); // Задавам нови насройки на базата
}
}

class E extends A {

public function B() {
parent::__construct(); // Задавам нови насройки на базата
}
}

$B = new B();
$B->A1();
$B->A2();
$B->A3();

$C = new C();
$C->A1();
$C->A2();
$C->A3();

$D = new D();
$D->A1();
$D->A2();
$D->A3();

$E = new E();
$E->A1();
$E->A2();
$E->A3();

Така всеки нов обект задава нови настройки за връзка с база данни и използва методие на родитеслкият клас за обработка на получените данни.

До тук добре. Всичко работи, но скоростта опрделено не е оптимизирана. Дванадесет заявки са много. Затова измислих следното решение. Добавих допълнителен метод в родетелският клас, който извлича всичките суми, чрез вътрешни заявки ( sub query / queries ), създава се  инициализиращ масив, а останалите методи ще обръщат към него. Да де, ама така излиза, че пак ще се правят 12 заявки, като този път ще са и по-сложни. И да и не. Тук идват на помощ статичните данни. Инициализираме един статичен масив във всеки от дъщерните класове, който ще предваме по референция. При извикването на метода, който извлича всичките данни ще се прави проверка, дали тези данни са вече записани в статичният метод – ако да използваме тях, ако не са – извличаме ги. Ето и примера:

class A {

public function A0( &$arr ) {
if( sizeof( $arr ) == 0 ) {
// Извлечи, обработи и запиши данните в $arr масива
}
return $arr;
}

public function A1() {
$a = $this->A0();
return $a[‘A1Result’];
}
public function A2() {
$a = $this->A0();
return $a[‘A2Result’];
}
public function A3() {
$a = $this->A0();
return $a[‘A3Result’];
}
}

class B extends A {

protected static $arr;

public function B() {
parent::__construct(); // Задавам нови насройки на базата
}

public function A0() {

return parent::A0( &$arr );
}
}

class C extends A {

protected static $arr;

public function B() {
parent::__construct(); // Задавам нови насройки на базата
}

public function A0() {

return parent::A0( &$arr );
}
}

//  Тук кодът продължава като първият пример

Ако нещо не сте разбрали или имате предложения – чувствайте се свободни да пишете коментари.

Categories
Лично творчество Статии

Singleton, static и други подобни PHP щуротии

Какво точно е Singleton и какво са статичните данни? На този въпрос се опитват да си отговорят колегите от BGDev. Тук ще се опитам да хвърля малко светлина по въпроса.

Първо що е то статична данна?

Статични данни са такива, които са “живи” през целият период на изпълнение на приложението. Най-добре ще ме разберете с пример.

function static_test() {

static $a = null;

if( $a == null ) {
$a = 1;
echo ‘Първо извикване на функцията’;
} else {
echo ‘Всяко следващо’;
}
}

static_test();
static_test();

Ха сега, познайте какво ще се покаже при първото и после и при второто извикване?

След като очевидно схванахте как се използват статични данни нека да спомена, че за да може да имате достъп до статични данни в клас ( PHP, Java, а предполагам и други езици ) трябва да дефинирате метода си като статичен. Готиното на статичните методи, е че можете да ги извиквате без да се нуждаете от  създаване на обект. Пак пример?

class StaticTest {

private static $test = “test”;

public function getTestNonStatic() {
echo $this->test;
}

public static function getTest() {
echo self::$test . ‘<br />’;
}
}

$StaticTest = new StaticTest();
$StaticTest->getTestNonStatic();

StaticTest::getTest();

Въпросният код дава следният изход:

Notice: Undefined property: StaticTest::$test in …
test

T.e. имате достъп до статични данни само от статични методи.

Сега малко за Singleton. Няма да обеснявам какво е Singleton, а направо ще ви покажа пример за Database клас, който използва такъв шаблон.

class Database {

private static $instance = null;

public static function getInstance() {
if( !self::$instance instanceof self ) {
self::$instance = new self;
}
return self::$instance;
}

private function __construct() {
global $host, $user, $pass, $dbname;

$this->connect( $host, $user, $pass, $dbname );
}

private function connect( $host, $user, $pass, $dbname ) {

$this->host = $host;
$this->user = $user;

echo ‘Host: ‘ . $host . ‘<br />’;
echo ‘User:’ . $user . ‘<br />’;
echo ‘Pass:’ . $pass . ‘<br />’;
echo ‘Name:’ . $dbname . ‘<br /><br />’;
}

public function query( $sql ) {

echo ‘Host: ‘ . $this->host . ‘<br />’;
echo $sql . ‘<br /><br />’;
}
}

$host = $user = $pass = $dbname = “Testing”;

$DBI = Database::getInstance();
$DBI->query( “SELECT .. “);

$DBI2 = Database::getInstance();
$DBI2->query( “INSERT INTO ..” );

Тук ще се наложат малко пояснения явно. ОК. Singleton шаблона е перфектен за извикване на инстанция на клас за връзка с база от данни. Защо? Защото хем е глобален т.е. можем от всяко кътче на PHP кода да си го да извикаме, хем прави само един път връзка към базата … а не 100, ако създавахме обект всеки път. Когато създаваме $DBI обекта, чрез статичният метод getInstance() всъщност се прави проверка дали вече е създаден въпросният обект. Ако не .. тогава правим нов, ако е – връщаме инстанция към него и го използваме. Катко забелязвате ( всъщност може да забележите тук 🙂 ) Данните за host, user, pass и т.н.т. се показват само един път от connect метода т.е. тук симулирам достъп до базата де .. но виждате резултатът. Та това е “сложният” Singleton шаблон.

Ако имате въпроси използвайте формата за коментари по надолу 🙂