Постове 1 - 5 от 7 с таг Pixeldepo

Aug 17

Днес почетох този пост във veselin.bg, пробвах в един коментар да събера най-основните “стандарти” по който пиша PHP код. Обаче коментарът доста набъбна и реших да го направя като пост.

В PHP за разлика от повечето (да не кажа всички) програмни езици няма точно установен стандарт структориране и писане на кода. Донякъде това се дължи на самата история на езика и това, че написан на PHP3 код може да върви дори и на PHP6. От друга страна PHP се води най-лесния за учене език, точно защото каквото и да напишеш все ще ти излезе резултат. Тази страна на PHP колкото и позитиви да има, като цяло според мен е грешка на самия език и придава малко статус “аматьори” на PHP програмистите му.

В послените години започват да се оформя що годе няколко стандарта на писане, но като цяло поне според мен докато PHP5.3 – PHP6 не започне да се ползва масово нещата няма много да се променят.

Основния начин да се започне да се работи по стандарт е да се работи с някой PHP framework, защото всички те си имат свой достатъчно добре дефинирани “стандарти” и самия framework ви кара да пишете по неговия стандарт за да изглежда кода ви добре. И тъй като никой PHP framework неможа да ме спечели, аз си направих мой. Който вече от 1 година се ползва във всички проекти които правя за Pixeldepo ( и които са на PHP разбира се ) и съм страшно доволен от това как работи. В неговите coding conventions съм “взаимствал” доста идеи, главно от  Zend Framework и CodeIgniter.

Именуване на променливи и функции и методи.

Променливите и методите ми са със CamelCase, фунцкиите са с подчертавки. Което е малко старанно за повечето хора, но поне според мен има известна логика ( иначе нямаше да пиша по този начин де :) ). Самия PHP, като език ако се погледне дългия списък със фунцкии ще се види че основно те са с почертаване и когато се ползва фунция инстиктивно знам че е такава. Докато класовете  (повечето от тях) използват CamelCase стандарт подобно на Java и когато се работи с класове изглеждат някак естествено. По принцип използвам много малко фунции и обикновенно те са просто wrapper/shortcut към някой клас.

Не използвам долни черти за разделянето на private променливи фунции. Пример за променлива / фунция / метод

$name = '';
$totalPrice = "";

function url_for($params){ /* ... */ }

class Foo {
public function isValid(){ /* ... */ }
}

Именуване на класове

Начина на именуване на класовете в Zend Framework, ми допадна най-много, от висички останали които бях гледал в различни PHP-та. Общо взето идеята е в името на класа да се съдърже “namespece” му. И същевременно класа да се намира в директория, пътя на която отговаря на това име. Примери:


// намира се в ActiveRecord/Plugin/Attachable.php
class ActiveRecord_Plugin_Attachable {}

// намира се в Model/Validation/Errors.php
class Model_Validation_Errors {}

// намира се в Tool/Script/Genererate/Applition.php
class Tool_Script_Generate_Application {}

Това е много ползено за _autoload на класове и доста ще улесни бъдеща интеграцията на PHP5.3 – PHP6 namespace-овете. Само да вметна, че доста хора не го знаеха за autoload, най-добре да се ползва spl_autoload.

Като тук проблема с абстрактните класове го решавам, като ако класа е абстрактен се кръщава Base. Тъй като Zend имаха проблем със класове като Zend_Controller_Plugin_Abstract, който в щеше да стане просто клас Abstract от PHP6 и щеше да е в namespace Zend\Controller\Plugin.  А Abstract е ключова дума и неможе да има клас който се казва така. При мен такъв клас се казва просто Base.

С подобна структура на класовете е много удобна и въпреки че много хора казват, че с такива имена писането става трудно.  Има доста техники с който се избягва писането на целите имена. Като пример ще дам моята script функция която изпълнява script  класове.

script('generate:model'); // Прави клас Tool_Script_Generate_Model го изпълнява
script('db:dump:data'); // Прави клас Tool_Script_Db_Dump_Data и го изпълнява

// като могат много лесно се добавят плъгини:
script('your:custom:script'); // Това е клас Tool_Script_Your_Custom_Plugin

В заключение…

Основната идея на стандартите е не само вие да може да си разчетете кода след 1-2 месеца, но и други хора да могат да работят над него. Също така е важно и да не ви е толкова срам от него след време, което рядко ще стане, но е важно да се опита. Kода да изглежда естествено в средата в която работите било то PHP / Ruby / Java и т.н. За PHP това не е лесно, защото самия език не изглежда естествено понякога.

За стандарти за писане лично аз препоръчвам тези на Zend Framework и донякъде тези на CodeIgniter. Ако пишете изцяло собствени неща, ако не пишете по стандартие на системата в която сте.

To be continue…

Това е тема с продължение, която най-вероятно утре ще продължа :)

Тъй като исках да напиша още за коментари / гетъри и сетъри / php файлове плюс няколко други неща, ще има още един пост.

Ако имате някви коментари и / или съвети може да ги споделите. Също така ще се радвам и да чуя и по какви стандарти пишете и вие.

Jul 02

Получих покана от Веселин Тодоров да участвам в инициативата подхваната от Марио Пешев за това как протича една работна седмица.

Добре, че ме хвана след края на семестъра, защото когато трябва да посещавам университета, програмата ми е много странна и разпъната. И е тясно свързаната с програмата от университета. Сега след края на семестъра, вече не работя дистанционно от Варна. И от около една седмица съм в Добрич и ходя работа в офиса на pixeldepo, където работя.

kancelarijaubuducnostiru2

Така, как протича един мой работен ден? Или поне как най-вероятно ще протича, базирано на това как мина тази седмица и как беше миналата и по-миналата година.

Ставам към 9 – 9.30

Едно от нещата, който наистина много мразя е да ставам рано (за мен 7 сутринта е време за лягане не за ставане). Будилника ми е настроен да звъни на три пъти – 9.00 / 9.10 / 9.25 и обикновено до към 9.30 съм станал. В следващите 20-30 минути, в зависимост кога съм станал имам време за душ, закуска и други подобни. В 10 часа вече съм тръгнал за офиса или ако шефа минава покрай нас по това време ме качва до офиса.

Начало на работния ден към 10.05 – 10.15

Офиса е на буквално 5 минути път от вкъщи(то маи в Добрич всичко е на 5 минути). Лошото е, че се минава през един доста стръмен баир. Но няма перфектни неща. И така към 10.10 съм вече на работа.  Първото нещо което правя е да проверя дали има спешни неща за правене до обяд и какво има да се прави като цяло за деня. Ако има нещо спешно се работи по него. Но когато няма, идва ред на “прегледа на печата” и на задачите – GMail / Basecamp / GReader / Twitter / Todoist / Taskar.  От там си заделям неща, за обедната почивка или video-та за слушане докато работя по нещо по-просто. Общо взето в преди обедния период не съм много продуктивен.

Периода между 11 – 12 часа

Това е може би най-странния и период от работния ми ден. В зависимост от това дали трябва нещо да контактувам с клиенти / да разпределям работата на колегите по проектите в който работя / да се направи нещо спешно като оправяне на бъг или добавяне на нов модул някъде, правя най-наложителното. Но в общия случай това е момента в които помагам на колеги или се осъжда нещо около текущия проекта.

Обедна почивка между 12 – 13 ~ 13.30

В общия случаи има два варианта за обедната почивка. Първия е да отидем някъде с нечия кола да обядваме навън с колегите. А Втория вариант е да “магазиним” ( т.е. ходене до магазина) и после да се обядва в офиса докато се четат / гледат / препращат / обсъждат нещата които са били отбелязани в “прегледа на печата”.

Същинската работа 14- 17.30

Това е най-продуктивната част от деня ми. Това е периода в които работата която върша е най-качествена и най-бързо работя. Обикновено докато работя и съм си намерил някоя интересна презентация, я слушам докато кодирам вместо музика. И нещата стават още по-добре.  Като цяло шума излизащ от мен намалява в този период и само при нужда се раздвижвам (като да се помогне с нещо на колега) .

Около 17.30 – 18.00 когато е края на работния ден пак намалявам оборотите. За да видя дали ще може да се остане в офиса след работно време до към 19 ~ 19.30 ~ 20 примерно. Защото обикновено ни “гонят” в 18 от работа (колкото и странно това да звучи).

Ако се остане след 18.00 пак имам пик в продуктивността, съпоставим с периода 14 – 17.30. Това си го обяснявам с това, че в офиса оставаме най-често аз и Добромир Райнов и климатиците, които вече не трябват, не бучат. И целия офис излъчва някакво спокойствие и уют по това време.

След края на работния ден

Когато съм във Врана има много различни неща за правене. Но Добрич в това отношение е малко по-скучен град, а и се оказва че повечето ми познати и приятели са във Варна. Така че след работния ден не ми е много интересен. А и още само една седмица съм тук и нямам много идеи какво да правя след работа. Надявам се най-сетне с брат ми, да започнем пак да ходим на фитнес или на някакъв друг спорт.

Събота – Неделя

Още не знам какво ще правя тези дни. Най-вероятно Събота ще спя до обяд. Ще ходя да се видя някои друг познат във Варна. Ще работя по някои личен проект или opensource проект. И ще блогвам сигурно. Но времето ще покаже.

Станков Live

По план от другата седмица в Сряда започва втори сезон на “Станков Live”. Това е малко нещо което правя всяка сряда някъде между 12.30 ~ 14.30 на работа. Тогава събирам колегите и говорим (т.е. главно аз говоря) за нови технологии, методологии и други интересни неща около последните проекти. Като цяло си обменяме опит и си сверяваме часовниците.  Поне от миналогодишния сезон си мисля, че доста добри неща произлязоха от това. Надявам се тази година да съм по-добър :)

Горе долу такава беше последната седмица. И такава би трябвало да ми е програмата за няколко то месеца до началото на новия семестър и до моето завръщане във Варна.

Тъй като инициативата е готина предавам щафетата на всеки, които я иска :) Малко късно се включих и затова много хора вече са писали доста интересни неща.

Jun 22

Измина малко повече от година (1 година и 4ри дни да сме точни) от излизането на Firefox 3. Още със самото си излизане подобри рекорди. Но мина една година и какво се случи през нея със Firefox и браузърите като цяло.

browser wars internet explorer vs firefox vs safari vs opera

Като начало всички вървят напред към HTML5, доста браузъри вече имат html5 благини като <canvas>/<video>/Selector API/Storage/Data Attributes.

Същевременно има и нова версия на EcmaScript – 5 (т.е. JavaScript) и се очаква до края на година в браузърите да започват да се появяват части от новата спецификация. Която поне на хартия изглежда много обещаващо.

Но да се върнем на темата

Firefox

И след като беше подобрен рекордът брояча за свалянията на Firefox работи и момента е на скромните – 28,340,281.

В момента аз съм със версия Firefox 3.0.11. Преди време бях писал за 3.1, но такава версия няма да има. Поради факта че в 3.1 има много промени по Firefox версията ще е номерирана 3.5 и се очаква да излезе до месец най-много. За нея имам надеждата, че ще стане както при Firefox 2, която се водеше бавна, и заемаща много RAM. И при излизането на тройката всичко беше перфектно. Сега година след това отново се чува от всякъде за версия 3, че Firefox е бавен и много тежък. Така че много се надявам 3.5 да е достатъчно бърз. И от тази статия Chrome and Firefox 3.5 Memory Usage – поне нещата изглеждат много добре.

Друго нещо за което много чакам 3.5 са и няколко CSS добавки, които въпреки че не се виждат под 3.0 ги ползвам в 90% от административните модули на сайтове, който правим в pixeldepo. И така при самото излизане на 3.5 ще има доста доволни клиенти :)

Safari

Преди няколко седмици излезе версия четири, която утвърди Safari като един от най-добрите браузъри. Също така Safari е много близо до това да замени Firefox като браузъра, който ползвам всеки ден. Общо взето ако ги имаше “малките неща” от Firefox в Safari, щях да съм забравил отдавна за Firefox. Но ако Firfox 3.5 не скъси малко границата със Safari може и да забравя тези неща. Защото за момента според мен Safari е най-добрия браузър на пазара.

Chrome

Chrome, беше изненадващ ход от страна на Google, за него писах няколко пъти тази година. Това, че ползва WebKit, го прави много лесен за работа, т.е. да правиш неща за него. Подобно на Safari-то с него съм нямал проблеми до сега. Има красив интерфейс и много ме радва, че все повече познати го ползват.

Opera

Като стана дума за проблеми. Opera е браузърът който ми е създавал най-много главоболия тази година. Даже повече от IE6! Това се обяснява с факта, че като цяло Opera е малко използван и бъговете за него не са толкова известни.

Но за самата Opera как беше година? По различни статистики Opera най-много пострада от Chrome. Голяма част от пазарния дял на Chrome идва от този на Opera (което мен лично ме радва).

Друго интересно нещо е че Opera 10b идва, което е проблем за много js библиотеки. Тъй като е първия браузър който стига двуцифрен номер, той има честа да се сблъска с Browser Detection проблем. Т.е. за много библиотеки Opera 10 е Opera 1, защото вземат само първото числи от версията на браузъра :) Затова Opera 10 ще се води версия 9.8 (нещо като това че Windows 7, същност ще е 6.1)

Internet Explorer

При IE-та също не беше много тихо тази година. Продължава борбата за намаляване на IE6 и доста хора и компании спряха  да грижат за IE6, което според ме е правилното решени.

Излезе IE8, като единственото добро нещо което може да се каже за него, е че е доста по-добър от IE7. Все още е светлинни години от добрите браузъри като Firefox, Safari и Chrome, че даже и от Opera. Няма да забравя първия път като го пуснах, колко грозен ми се стори целия му интерфейс. Като цяло са налага на Microsoft да дават $10 000 на хората за да го ползват (което ми напомня за тази Mac vs PC реклама).

И като стана дума за Microsoft и реклама,  за IE8 беше пусната и доста смешна (да не кажа по-остра дума) таблица с това колко IE8 е по-добър от Firefox / Chrome. Самата таблица като я гледах и си мислех кое от кое звучи по-смешно – Performance, Web Standards или Developer Tools, не можах да избера. Всичко изглежда толкова смешно и жалко. Дано не и се вържат много нормални хора, защото не вярвам някои нормално мислещ developer да се хване.

За повече информация относно IEтата, препоръчвам тази статия: QuirksBlog: State of the Browsers – IE edition

IE browser market

Заключение

Миналата година беше доста интересна и забавна и според много хора маркира началото на новите Browser Wars. До колко това е така, всеки може да прецени за себе си. Но поне според мен бъдещето е доста светло – по-бързи браузъри, по-вече стандарти ( в добрия смисъл на думата), html5, подобрен javascript, по-малко IE6 :)

Apr 18

Наскоро (преди около месец де) излезе Prototype 1.6.1 RC1, основната цел на тази версия е съвместимост с ново излезлият IE8, и Element.Store ( за който бях писал преди време ).

Toчно за  Element.Store исках да драсна някои ред, защото изненадващо за този тип storage няма много материали в нет-а.

Основната идея на Element.Store е да може да се добавя информация (като обекти) към даден  елемент, без да се страхуваме от memory leaks. Това в Prototype е реализирано със следните методи (под $(element) имам предвид референция към prototype extend element):

  • $(element).getStorage() – директен достъп до Storage-а на даденият елемент,  той просто представлява един Hash в който се запазват всички обекти, които искаме да прикачим към елемента. Дефакто store/retrive се явяват shortcut-и на get/set методите на този Hash.
  • $(element).store(key, value) – записва информация в даденият елемент, ключът трябва да е string (или обект с метод toString), после когато искаме да си вземем информацията отново използваме ключа. Възможно е наведнъж да се запишат повече от една двойка ключ – стойност: $(element).store({ key1: ‘value1′, key2: ‘value2′ /* и така на татък */});
  • $(element).retrieve(key, defaultValue) – извлича информация от елемента по даден ключ, като ако не съществува такъв ключ се връща  defaultValue.
  • вероятно $(element).unsetStorage() (ticket | gist) – този метод все още го няма, но е много вероятно да се появи във финалната 1.6.1 версия, той трябва да премахва цялата информация за дадения обект от Storage-a му. Ако искате в момента да ползвате unsetStorage може да вземете моята примерна версия от тук.

Как обаче това би се ползвало в реалния свят ? Първо най-вероятно във финалната версия 1.6.1 цялата event система на Prototype ще използва Element.Store. А аз ще си позволя да дам един малък пример за това как и къде се ползва Element.Store:

Имаме примерно масив с футболисти на Арсенал, и на страницата имаме бутони, чийто id-та се образуват от ‘button_’ + номера на футболиста. Целта е при натискане на бутон за даден футболист да се показва името му с alert.

var footballers = [
	{number: 14, firstName: 'Theo',     lastName: 'Walcott'},
	{number: 12, firstName: 'Carlos',   lastName: 'Vela'},
	{number: 23, firstName: 'Andrei',   lastName: 'Arshavin'},
	{number: 4,  firstName: 'Francesc', lastName: 'Fabregas'},
	{number: 5,  firstName: 'Kolo',     lastName: 'Toure'},
	{number: 25, firstName: 'Emmanuel', lastName: 'Adebayor'}
];

Общо взето без имаме 4 възможни варианта:

// Вариант 1: използваме closure за достъп до футболиста
footballers.each(function(f){
	$('button_' + f.number).observe('click', function(){
		alert('#' + f.number + ' ' + f.firstName + ' ' . f.lastName);
	});
});

// Вариант 2: използване на скит closure
function show(f){
	alert('#' + f.number + ' ' + f.firstName + ' ' . f.lastName);
}

footballers.each(function(f){
	$('button_' + f.number).observe('click', show.curry(f));
});

// Вариант 3: използване на референция в самия обект
function show(){
	var f = this.footballer;
	alert('#' + f.number + ' ' + f.firstName + ' ' . f.lastName);
}

footballers.each(function(f){
	var button = $('button_' + f.number);
	button.footballer = f;
	button.observe('click', show);
});

// Вариант 4: използване на Element.Store
function show(f){
	var f = this.retrieve('footballer');
	alert('#' + f.number + ' ' + f.firstName + ' ' . f.lastName);
}

footballers.each(function(f){
	$('button_' + f.number).store('footballer', f).observe('click', show);
});

Всички варианти работят и правят едно и също (или поне така си мисля :) ), но всеки си има и своите особености. Така Вариант 1 изглежда добър вариант и също така е доста се използва именно този метод, но това което ме притеснява е че анонимната функция към бутона се пре-декларира за всеки бутон (въпреки, че това пак зависи от интерпретатора). Също така при по сложни скриптове може да се получат обърквания кое от къде идва и на къде отива, а и от самия код не е много “чист”. Във Вариант 2 се използва curry, което прави кода малко по-чист, но въпреки, че не е веднага видимо пак се използва closure ( в curry метода ) и отново има генериране на доста анонимни функции.  Вариант 3 променя още структурата кода, като се маха curry, и се добавя референция към футболиста в самия обект, така не се генерират множество функции, но вероятността да се появят memory leak-ове е много голяма ( а и самия код изглежда най-зле от всички варианти ). За мен лично вариант 4 е най-удачния (особено при по-големи проекти), сега към обекта пак се записва референция към дадения футболист, но този път се използва безопасния Element.store .

Надявам се с този малък пример да съм показал част от възможностите който предоставя новия Element.Store механизъм и защо е полезен той :)

В заключения ще дам за пример с CD3.Select класа ми, който се използва за правенето на custom html select контроли. Като просто като се напише new CD3.Select(selectElement), автоматично selectElement-а се замества с група от div/ul/li елементи и така се дава възможност на дизайнерите ни в Pixeldepo, да ги настройват както намерят за добре (всъщност в моите ControlDepo 3 Widgets имам още цял арсенал от компоненти, с подобни функции). Та преди в CD3.Select за капсулирането на връзката между options обектите и техните производни li елементи използвах closure, като след появата на Element.Store промених нещата. При което се забелязах че доста по-добре и глатко  работят самите контроли и много по-малко памет се използва :)

Element.Store използвам още за Event.deletege, който много се надявам да попадне в core-a на Prototype.js и за който в следващата седмица мисля да напиша един пост.

Dec 01

Работейки по новата ми CMS система – Control Depo 3 ми се наложи да имам малко по advanced конфигурационен файл, така че за в бъдеще да ми е по-лесно да се наместват различните части на системата. Преди ползвах стандартното за едно PHP приложение – един файл config.php:

// start config
$_CONFIG = array();

// database
$_CONFIG['db_host'] = 'localhost';
$_CONFIG['db_name'] = 'project';
$_CONFIG['db_user'] = 'root';
$_CONFIG['db_pass'] = 'password';

// languages
$_CONFIG['default_language'] = 'bg';
$_CONFIG['laguages'] = array('bg' => 1, 'en' => 2, /* ... */);

// session
$_CONFIG['session_salt'] = 'SD23aeda';
$_CONFIG['session_expire'] = 4*60*60;
// ... и така много много реда код

После тази глобална променлива( $_CONFIG) когато ми трябва се вика със global и се ползва. Обаче от една страна че не е много красиво така написано, но от друга и това с global просто прави кода малко разхвърлян(на английски имат страхотна дума за това – messy) .

Това което ми трябваше основно е може да имам няколко enviroment конфигурационни файла подобно на Rails. Другото важно нещо беше да се побира в един екран, така че да не се налага да скролирам и да мога с един поглед да виждам всичко което ми трябва. И естествено да не е много сложно и да работи достатъчно бързо.

Първо погледнах Zend_Config, защо все пак са component-based-framework и може директно да видя как работи конфигурационната им система. И общо взето това което видях не ми хареса въобще. Много ми напомня на LEGOs, Play-Doh, and Programming от Jamis Buck, за която бях писал преди време(даже има я качена на видео в confreaks заедно с цялото rubyconf 2008).
От една страна колко пъти ще искам да ползвам XML и INI за конфигурация?! От една страна php си има array(), с която идеално може да се запишат всички неща който ни трябват и да са достатъчно четими. От друга самото четене на огромен xml/ini/yml/… файл отнема време и ресурси и са доста по-бавни от прост php код.

Добре че поне тук от Zend са сложили подразбиране да се ползва само php масив. Но от тук дойде 2рото ми учудване. Това а именно самата работа на имплементация на Zend_Config. Идеята е доста проста подава се масив, който се обгръща(wrap) от Zend_Config обект и след това се работи само със Zend_Config обект. Пример:

// Create the object-oriented wrapper upon the configuration data
$config = new Zend_Config(array(
'webhost'  => 'www.example.com',
'database' => array(
'adapter'   => 'pdo_mysql',
'params'    => array(
'host'      => 'db.example.com',
'username'  => 'dbuser',
'password'  => 'secret',
'dbname'    => 'mydatabase'
)
)
));

// Print a configuration datum (results in 'www.example.com')
echo $config->webhost;

// Use the configuration data to connect to the database
$db = Zend_Db::factory($config->database->adapter,
$config->database->params->toArray());

// Alternative usage: simply pass the Zend_Config object.
// The Zend_Db factory knows how to interpret it.
$db = Zend_Db::factory($config->database);

Идеята като цяло е много хубава, и при добро желание може човек да си направи основната част класовете му приемат Zend_Config обекти. Но има едно НО и то доста голямо. Защо ние е това? Единствения плюс който се сетих е че може да се направи immutable config обект. Но за сметка на това ще има доста излишен код и много памет за съхраниението на Zend_Config обекти и техните атрибути. А и колкото и да обичам __set/__get магиите тук ми се виждат напълно излишни защото както в примера:

$config->database->params->toArray()
// Това би представлявало нещо такова като backtrace
$config->__get('database')   // магически се търси атрибута 'database'
$config->_data['database']   // това което се връща тук пак е Zend_Config обект, който ще го нарека $object
$object->__get('params')     // пак същото за
$object->_data['params']     // друг $object
$object->toArray();          // автоматично всеки Zend_Config обект, който се стрещне му се вика Zend_Config::toArray()
$object->_data               // това за което ни трябва

Zend_Config си има и своите плюсове(immutable, секции, default стойности) и може за някое наистина “enterprise” приложение с много разчленена конфигурация (и много стабилен и мощен сървър :) ) да върши работа. Но не е за мен и аз си предпочитам “голите” array(). Все пак

No code is faster than no code

- някъде го чух това.

Така че какво реших ? Ами в предишния ми пост – PHP tips – include и return, описах метода за връщане на стойности от php файл и реших него да ползвам плюс малко правила и подрежанки. Сега имам следните файлове:

  • /config/config.php – тук ще е основната конфигурация
  • /config/enviroment/ – в тази папка ще се съдържат конфигурационните файлове за различните среди за работа, като стандартно имам 3 вида среди
  • /config/enviroment/development.php
  • /config/enviroment/test.php
  • /config/enviroment/production.php
  • /config/mailer.php – тук ще има конфигурация за mail системата, тя е изнесена в отделен файл, защото тук няма само да се връщат config данни, а и ще се вързва към smtp сървър (ако трябва), ще се настройват достъпи и други подобни неща. За разлика от другите конфигурационни файлове mailer.php се вика само когато се налага да се изпращат писма не по-рано.
  • /config/routes.php – това са настройките ми за различните пътища, подобно на Rails (пак)

Това са различните конфигурационни файлове (поне за сега).

return array(
'database'  => array(
'engine'    => 'mysql',
'host'      => 'localhost',
'name'      => 'project',
'user'      => 'root',
'pass'      => 'password'
),
'i18n'      => array(
'default'   => 'bg',
'languages' => array('bg' => 1, 'en' => 2, /* ... */)
),
'session'   => array(
'engine'    => 'cookie',
'salt'      => 'vW34Aaasa',
'expire'    => 4*60*60
), // на последния ред имам , защото при добавяне на нов ред да не ми се налага да я слагам
// а и SVN/Git ще го сметне като изтрит ред и после добавен ред
// ... още конфигурация ...
);
// /config/enviroment/development.php - примерно
return array(
'database'  => array(
'engine'    => 'mysql',
'host'      => 'localhost',
'user'      => 'root',
'pass'      => '',
'name'      => 'project_dev'
),
'smarty'    => array(
'compile_check'     => true,
'force_compile'     => false,
'debugging'         => false,
'caching'           => false,
'cache_lifetime'    => 0
),
'logging'           => true,
'display_errors'    => 1,
);

А в bootstrap-а имам просто това


// ENVIROMENT е просто константа в която казва в кой режим на работа е приложението
$_CONFIG = array_merge_recursive(include($_CFGDIR . '/config.php'), include($_CFGDIR . '/enviroments/' . ENVIROMENT . '.php'));

// ... код ...
// общо взето извличам всичко което ми трябва от $_CONFIG и го разпределям по обекти
// така че да не ми трябва повече $_CONFIG
// ... код ...

unset($_CONFIG /* заедно с още няколко вече не потребни ми променливи */);

Това решение ми се вижда най-елегантно, в моя случай. Може и да не може да се нарече “система” но е достатъчно надежно и ефективно да ми свърши работа. Все пак съм фен на Convention over configuration И ако ми се наложи да имам подобен на Zend_Config обект, с които да работя мисля да не променям основните неща, а просто този обект да използва ArrayAccess, но за това друг път, че сега май малко по-дълго стана от плануваното.

Надявам се някой да намери този пост полезен и ако съвети и идеи ще се радвам да ги чуя :) .