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
Работа Статии

Campaign Monitor, PHP4

Като работа за последният ми проект, трябваше да интегирам Campaign Monitor ( все го бъркам с Manager ). Това е софтуер за бързо и лесно изпращане на писма до клиенти ( т.е. масово спамене ). За мой лош късмет, точно в момента разработчиците решават, че трябва да внесат промени и премахват примерите ( samples ) и инструментите за работа с API-то им ( API kit ). Логично веднага почнах да търся дали някой добър човечец не е написал подобен клас и след няколко проби през Google попаднах на следния Campaign Monitor клас ( Campaign Monitor class ) написан от Keri Henare ( Кери Хенаре ще го преведа на български ). До тук добре, нали? Проблемът се появи когато видях, че класът е написан за PHP 5, в което няма нищо лошо, стига сървърът, на който е проектът да не беше на PHP 4. Ще кажете “Голям прас. Драсни един handler за PHP5 и всичко ще заспи”. И при други обсоятелства бих се съобразил с вас, но никак не исках да превключвам версията на сървъра, защото проектът не съм го писал изцяло аз, а е доста посещаван сайт и не знам откъде може да изкочи проблем ).

Затова реших да преправя класът от PHP5 към PHP4. След като разкарах private, public, protected декларациите за функции и данни, след като премахнах статичните извиквания или добавих обекти за тях се заех с функционалността. Буднах малко тук, малко там … и в крайна сметка се оказа, че трябва да бутна мнооого сериозно по функцията за превръщане на XML към Array ( XML to Array ). Бе направо я изтрих и я написах отново, само че да работи за PHP4.

И тук дойде другата ми изненада. domxml_open_mem фунцкията не съществува в PHP5!? Защо сте я махнали, бре? На кого му пречеше? Това е проблем, защото знам ли кога hosting компанията ще реши масово да премине на PHP5 ( а защо не го е направила до сега? ) и трябваше да си подсигуря стабилността ( сравнително ) на моята работа и на PHP5. Тук за пореден път много полезен се оказа Google. Оказа се, че фунцкиите за DOMXML ги има написани на PHP, а не за PHP. Copy/paste, една проверка дали е PHP 5, малко тестове на PHP5 сървър и съм готов.

Вдъхновен от Open Source движението реших да публикувам PHP4 версията на Campaign Monitor класът, както и съпровождащият го клас за правилна работа с XML на PHP5.

Campaign Monitor for PHP4 including Dom-xml-php4-to-php5

Не вярвам на някой да му потрябва, но знае ли човек ….

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 шаблон.

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