Programiranje

Apache vhost za ZF aplikacije

Da bi se olakšao deploy aplikacija napisanih u Zend Framework-u dodajemo dvije postavke u apache-ovu vhost datoteku:

<VirtualHost *:80>
	ServerName test.mysite.com
	ServerAdmin webmaster@test.mysite.com
 
	SetEnv APPLICATION_ENV testing
	php_value include_path ".:/web/zf/1.10/library:/usr/share/php"
 
	DocumentRoot /web/apps/mysite.com/public
	<Directory />
		Options All
	</Directory>
	<Directory /web/apps/mysite.com/public/>
		AllowOverride All
	</Directory>
 
	ErrorLog /web/logs/012-test.mysite.com-error.log
 
	# Possible values include: debug, info, notice, warn, error, crit,
	# alert, emerg.
	LogLevel debug
 
	CustomLog /web/logs/012-test.mysite.com-access.log combined
</VirtualHost>

SetEnv APPLICATION_ENV testing
ovim određujemo koji dio (sekcija) konfiguracije će se koristiti, ovo obično stavljamo u .htaccess datoteku projekta (ili postavljamo u index.php prije samog bootstrapa aplikacije) - u ovom slučaju nema potrebe za naknadnim mijenjanjem deploy-anih datoteka, automatski se koristi ispravna konfiguracijska sekcija ovisno o serveru na koji je stavljena aplikacija
php_value include_path ".:/web/zf/library:/usr/share/php"
druga stvar koja se može mijenjati ovisno o serveru na kojem se izvršava aplikacija je putanja do samog Zend Frameworka, isto kao i APPLICATION_ENV, postavljanjem te putanje u index.php (ili neku drugu datoteku aplikacije) uvijek je trebamo upisivati kod deploy-a aplikacije na server, ako je upišemo u vhost uvijek ćemo imati ispravnu putanju bez obzira na kojem serveru je aplikacija
u teoriji možemo dodati putanju do ZF-a u php.ini, ali to bi se moglo pokazati kao problematično ako na istom serveru imamo više aplikacija koje koriste razne verzije ZF-a ili nekih drugih lib-ova

Ponekad sam glup

Već nekoliko dana pokušavam natjerati Drupalov Twitter modul da radi (ako se ovo pojavilo na twitter-u znači da mi je napokon uspjelo), ali bez ikakvog rezultata. Na mojoj lokalnoj verziji sajta je proradilo od prve, bez ikakvih problema. Na serveru jednostavno ne radi. Nikako.

Nakon nekoliko dana očajničkih pokušaja, čitanja raznih članaka (za koje se redovito pokazalo da nemaju veze s onim što je moj problem), kojekakvih brisanja cache-a (čak i direktnim izvršavanjem upita na bazi), provjeravanja dozvola datoteka modula i sl. konačno sam uspio pronaći uzrok problema. Naravno, bio je banalno jednostavan - datoteke twitter modula sam uploadao u direktorij starog bloga na habek.net (koji više ne radi) umjesto na potrebno mjesto na novom blogu na sinisa.habek.net.

Vjerojatno postoji neko pravilo koje govori da čim više vremena potrošite otkrivajući uzrok nekom problemu (iliti jednostavnije, zašto damn stvar ne radi kako bi trebala), to je taj problem jednostavniji (iliti gluplji). Ako takvo pravilo ne postoji, vjerojatno bi ga trebalo izmisliti. Blah. :-P

Jednostavna konfiguracija u ZF aplikacijama II

U prijašnjem postu sam opisao jednostavan način korištenja konfiguracije u Zend Framework aplikacijama, te sam na kraju naveo nedostatke koje ima takav pristup. U ovom postu će biti primjer konfiguracije logger-a (objekt preko kojeg se u aplikaciji logiraju događaji) kod kojeg su ti nedostaci izbjegnuti.

Ovaj put neće biti posebne konfiguracijske datoteke, a postaviti će se samo jedan konfiguracijski parametar za logiranje - log.path, tj. putanja u koju želimo da aplikacija sprema logove (stvaran primjer bi imao malo više parametara):

application/configs/application.ini:

[production]
 
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0
 
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"
 
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
 
log.path = APPLICATION_PATH "/../data/log"
 
[staging : production]
 
[testing : production]
 
[development : production]
 
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1

U bootstrap-u ne spremamo konfiguraciju kao u primjeru iz prošlog posta nego te podatke koristimo za kreiranje loggera, instance Zend_Log klase koju koristimo za logiranje. Naravno, logger se sprema u registry iz kojeg ga možemo dohvatiti i koristiti iz bilo kojeg dijela aplikacije (naravno, stvarni bootstrap bi imao malo više toga):

application/Bootstrap.php:

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
	protected function _initAutoload()
	{
		$autoloader = Zend_Loader_Autoloader::getInstance();
 
		$moduleLoader = new Zend_Application_Module_Autoloader(array(
			'namespace' => '',
			'basePath' => APPLICATION_PATH
		));
 
		return $moduleLoader;
	}
 
	protected function _initLogger()
	{
		$options = $this->getOptions();
 
		$logger = new Zend_Log(
			new Zend_Log_Writer_Stream($options['log']['path'].'/log_'.date('Y-m-d').'.log')
		);
 
		Zend_Registry::set('logger', $logger);
 
		return $logger;
	}
}

Kad trebamo nešto logirati, logger čitamo iz registry-ja i pozivamo odgovarajuću metodu na njemu:

<?php
 
Zend_Registry::get('logger')->notice('Some application notice');

U usporedbi sa primjerom iz prijašnjeg posta:

  1. podaci iz konfiguracije se koriste samo u bootstrap-u, ako se promjeni struktura podataka u konfiguraciji biti će potrebno prilagoditi samo bootstrap - tipičan primjer bi bio ako npr. odlučimo umjesto logiranja u datoteku koristiti logiranje u bazu podataka
  2. u registry više nemamo spremljene parametre koje tek trebamo za nešto upotrijebiti već spreman objekt koji se može koristit - ako i postoji nešto što se ponavlja na svakom mjestu gdje se koristi to je već riješeno unutar njega

Jednostavna konfiguracija u ZF aplikacijama

Iako ovo baš nije najbolji način rada sa konfiguracijom može se upotrijebiti u jednostavnijim aplikacijama (u kojima ionako nema smisla previše komplicirati) ili kao brzi fix u nekoj većoj aplikaciji (s tim da bi u tom slučaju ipak to kasnije trebalo riješiti na neki kvalitetniji način).

Sami podaci se spreme u posebnu konfiguracijsku datoteku (u teoriji mogao bi se koristiti i application.ini), ali ako radite nešto takvoga sigurno se radi o parametrima koji se na neki način razlikuju i bolje ih je ne miješati sa ostalom konfiguracijom aplikacije. Npr. mogu se spremiti u options.ini datoteku:

application/configs/options.ini:

[production]
 
image.thumbnail.width = 80
image.thumbnail.height = 80
image.preview.width = 350
image.preview.height = 350
 
[staging : production]
 
[testing : production]
 
[development : production]

Konfiguracija se čita za vrijeme bootstrap-a aplikacije i sprema u registry:

application/Bootstrap.php:

<?php
 
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
	protected function _initOptions()
	{
		$options = new Zend_Config_Ini(APPLICATION_PATH.'/configs/options.ini', APPLICATION_ENV);
 
		Zend_Registry::set('options', $options);
	}
}

I na kraju, konfiguraciju koja je za vrijeme bootstrap-a spremljena u registry može se dobiti i koristiti kad god je to potrebno i iz bilo kojeg dijela aplikacije:

<?php
 
$thumbWidth = Zend_Registry::get('options')->image->thumbnail->width;

Loše strane ovakvog rješenja (zato i je upotrebljivo samo za jednostavnije slučajeve i fix-eve) su:

  1. aplikacija postaje vezana uz strukturu konfiguracijske datoteke - ako se zbog nečega promjeni struktura konfiguracije, morati će se isto ispravljati na svim mjestima u aplikaciji na kojima se ti podaci koriste (tj. čitaju)
  2. Zend_Registry i Zend_Config nisu baš previše pametne klase, još uvijek ćete morati sami odraditi provjere kod čitanja parametara i pokriti sve slučajeve koji su bitni (npr. nema traženog podatka, podatak nije ispravan i sl.), ako isti podatak opet trebate negdje drugdje morati ćete to isto ponoviti tamo
Syndicate content