ugrás a tartalomhoz

Leszármazott osztály könyvtára

inf · 2010. Júl. 28. (Sze), 00.19
Üdv.

Van egy ősosztályom, aminek a leszármazottjának a könyvtárát szeretném elérni.

valahol/leszarmazott.php:

class Leszarmazott extends Os
{}
os.php:

abstract class Os
{
    public function __construct()
    {
        $class=get_called_class(); // Leszarmazott
        $dir=???; // valahol
    }
}
Bármi ötlet?
 
1

Üdv !

whiteman0524 · 2010. Júl. 28. (Sze), 01.35

class Leszarmazott extends Os{
   public function getPath(){
      return getcwd();
   }
}

abstract class Os{  
   public function __construct(){  
      $class=get_called_class(); 
      $dir=$class->getPath(); 
   }  
} 
Szvsz. De persze lehet hogy nem jó :)
2

Szia!

inf · 2010. Júl. 28. (Sze), 10.59
Szia, az a baj vele, hogy a leszármazottba kell írni hozzá a kódot, akkor már __DIR__ is lehetne... Úgy lenne jó nekem, hogy az ős-ben adom meg a kódot, ami a leszármazott könyvtárának a nevét kéri le. (A leszármazott osztály php fájlja másik könyvtárban van, mint az ősé, és autoload tölti be. Elfelejtettem írni.)

Találtam kerülő megoldást, az autoload kezelő osztályomtól kérem le a leszármazott osztály könyvtárát (mert úgyis az tölti be). Eddig ott rontottam el, hogy a leszármazottat require_once-oltam, aztán ott akartam beállítani az autoload-ot. (Ennek is megvolt a maga oka, amit most megszűntettem.)
3

Koncepció?

janoszen · 2010. Júl. 28. (Sze), 11.06
Én a helyedben nem tennék mást oda, ahol a classok vannak. Ettől függetlenül, ha az autoloadod tud a fájlok helyéről, akkor az a legtisztább megoldás, ha tőle kérdezed meg.
4

Valóban

whiteman0524 · 2010. Júl. 28. (Sze), 19.36
Logikailag ez lenne a legjobb megoldás szerintem is :)
5

Milyen fájlok?

janoszen · 2010. Júl. 28. (Sze), 21.34
Egyébként csak úgy kiváncsiságból, milyen fájlokról van szó? Én úgy éreztem, hogy nagyon sarokba szorítom saját magamat, ha nem konfigurálható a nem-programkód-jellegű fájlok helye.
6

Huh, bonyolult. :-) Írok egy

inf · 2010. Júl. 28. (Sze), 23.12
Huh, bonyolult. :-) Írok egy kisebb enginet, aminek elég komplex a működése:

index.php:

require_once(__DIR__.'/../engine/bootstrap.php');
Engine\Autoload::instance()->put(__DIR__.'/../my_doc_root','Test');
Test\Server::instance()->respond();
Ilyenkor betölti az enginet, hozzáadja a document root helyét, meg a hozzá tartozó névteret. Innentől az Autoload tölti be a document root-ból a speckó fájlokat. (pl: speciális session kezelő, controller, model, view kezelők és a többi)

A document root kb így néz ki:

server.php
session
	my_session.php
...
project
	www
		project.php
		controller
		model
		view
		static
	static
		project.php
		controller
		model
		view
		static
	...
Ez kötött mappaszerkezet, a projecteket (ami a subdomain-hez tartozik) mindig a project mappából keresi ki a rendszer, amikor felépül a szerver.
A saját szerver meg az Engine\Server-ből van származtatva, és az Engine\Server konstruktorának kell indítania a keresést.

namespace Test;

class Server extends \Engine\Server
{
	public function __construct()
	{
		parent::__construct();
		$this->setSession(new \Engine\Session\BasicSession());
	}
}

namespace Engine;

abstract class Server extends Factory\Singleton
{
	protected function __construct()
	{
		$this->setPackage(...);//névtér beállítása
		$this->setDir(...);//mappa beállítása
		
		//request objektum létrehozása,beállítása
		$this->setRequest(new Command\Request());
		$this->getRequest()->getUri()->setUrl(
			'http'.(isset($_SERVER['HTTPS'])?'s':'').'://'.
				$_SERVER['HTTP_HOST'].
					$_SERVER['REQUEST_URI']
		);
		$this->getRequest()->getHeaderMap()->extract(apache_request_headers());
		$this->getRequest()->setContent(
			Resource\FileSystem\Factory::instance()->getStream('input')->getContent()
		);
		$this->getRequest()->getBrowser()->extract($_SERVER['HTTP_USER_AGENT']);
		$this->getRequest()->setMethod($_SERVER['REQUEST_METHOD']);
		
		//response objektum létrehozása, 
			//a hívott projekt állítja majd be a headert meg a tartalmat
		$this->setResponse(new Command\Response());
		
		//project factory létrehozása a projekteknek
		$this->setProjectFactory(
			Factory\Factory::instance()
				->decorate(new Factory\ContainerDecorator())
					->decorate(new Factory\StatementDecorator())
						->decorate(new Factory\SingletonDecorator())
		);
		//projektek hozzáadása a document_root/project mappából a project factory-hez
		foreach ($this->getDir()->getParent()->getDir('project')->getDirSet() as $dir)
		{
			$name=String\Camelizer::instance()->encode($dir->getName());
			$package=$this->getPackage().'\\Project\\'.$name;
			$class=$package.'\\Project';
			//a put hozzárendeli a projekt nevéhez az osztályát
			//a project neve most a példányosító metódus
				//kb így működik a factory osztályom:
					//$factory=new Factory();
					//$factory->put('getTest','Test');
					//$test=$factory->getTest(); 
			$this->getProjectFactory()->put($name,$class);
			//a prepare pedig a paraméter listát készíti elő
				//a ContainerDecorator azt jelenti, hogy
					//setter-es dependency injection-t használ: 
						//$instance->setName($name) a lentinél stb...
				//a StatementDecorator azt jelenti, hogy
					//előre meg lehet adni beállításokat a példányokhoz,
						//nem példányosításkor kell majd az arguments-ben
				//a SingletonDecorator azt jelenti, hogy
					//egy kulcshoz csak egy példányt hoz létre a rendszer,
						//és utána mindig azt kéri vissza
			$this->getProjectFactory()->prepare($name,array(
				'name' => $name,
				'package' => $package,
				'dir' => $dir,
				'server' => $this
			));
			//ezután a konkrét Server osztály elindítja a Session-t
			//utána a Server->respond-ot hívja az index.php
			//az meg ellenőrzi, hogy van e joga az illetőnek
				//az adott project,controller,action hívására
					//ha van joga, akkor átadja a kérést a projectnek, ami
						//beállítja a Server->getResponse()-t, aztán meg elküldi
					//ha nincs joga, vagy bármi hiba van, akkor
						//a hibakezelő rakja ki a megfelelő oldalt
			//nagy vonalakban durván ennyi a történet,
				//részleteiben meg sokkal bonyolultabb minden...
		}
	}
	
	...
}
7

Jó ez Neked

janoszen · 2010. Júl. 30. (P), 22.31
Te mondd, jó ez Neked? Ha más nem, a apache_request_headers() függvény használatáról szerintem, sürgősen szokj le, különben nem fogsz tudni átállni semmilyen más architektúrára (pl FastCGI). De én végig gondolnám azt is, hogy ez a bonyolult működési logika biztosan szükséges-e, hiszen egyrészt le kell futnia (minden requestre), másrészt nagyon sok működés be van drótozva (próbálj meg ehhez CLI-t írni), harmadrészt meg... próbálj meg erre unittestet írni.
8

Köszi a javaslatokat, request

inf · 2010. Júl. 30. (P), 23.48
Köszi a javaslatokat, request headert benéztem (pedig ott az apache a nevében...). :-)
Egyébként folyamatosan változik az egész, még képlékeny, meg fejlesztés alatt vannak az alapok is. Még nem tudom, hogy mik a lehetőségek, meg közben is tanulok, ezért nehéz unit testelni. :-)

Nekem az az elgondolásom, hogy unit test előtt meg kell tervezni az interfacet, meg hogy hogy fog működni, utána tesztet írni rá, és utána bekódolni, miközben folyamatosan ellenőrizzük, hogy a kód teljesíti e a tesztet. Na most ezt egy olyan rendszernél, ami még formálódik bennem, hogy hogy fog kinézni kicsit nehéz...
De simán lehet, hogy nem értem a unit test lényegét, mert még nem foglalkoztam vele behatóan.
9

Kezd beigazolódni, hogy

inf · 2010. Aug. 4. (Sze), 00.44
Kezd beigazolódni, hogy igazad van bizonyos dolgokban. :-)
Bár egyelőre csak kisebb részletekben... A bonyolult működési logikával kapcsolatban, tök felesleges az összes project mappáját előre kikeresni (a foreach az Engine\Server-ben), simán meg lehet tenni, hogy csak akkor kérjem le, amikor tényleg szükség van rá.... Érdekes megtapasztalni, hogy még egy viszonylag egyszerű programnál is simán lehet logikai hibákat elkövetni a fejlesztésnél. Végülis az interface-t a mostani rendszer is teljesíti, de minden lekérésnél egy csomó plusz fájlművelettel...

CLI-vel kapcsolatban az van, hogy nem szeretnék ilyet írni, mert nem igazán látom értelmét. Persze lehet, hogy van, de én még nem jöttem rá, hogy mi... Ha generáltatni akarok dolgokat, akkor weblapokból is elküldhetem az ehhez szükséges adatokat, ráadásul sokkal hatékonyabban lehet így paraméterezni a dolgokat. (vagy én nem értek valamit cli-vel kapcsolatban...)

UnitTest-ről csak most kezdek olvasgatni, hasznosnak hasznos, csak még nem szoktattam magam hozzá.
10

Csináltam új Factory-t, ami

inf · 2010. Aug. 6. (P), 03.15
Csináltam új Factory-t, ami sokkal gyorsabb, mint az itt használt, meg a könyvtár végignézése helyett inkább csak simán megpróbálom beszúrni a projectet, aztán vagy sikerül, vagy nem... A könyvtár végignézése még maradvány volt egy előző rendszerből, amit most felszámoltam.
Így Athlon64 3000-esen az összes autoload-dal együtt 8ms alatt áll fel a rendszer xdebug szerint. (A régi változat 40ms körül futott.)

A request és response objectek és a session kezelő felépítése meg szükséges a kérés lekezeléséhez.
11

Nem probléma

janoszen · 2010. Aug. 6. (P), 06.41
Ez így teljesen barátságos, a programnak azért működnie is kell. :)

Egyébként ami a CLI-t illeti, azért érdemes abban (is) gondolkodni, mert simán lehet, hogy szeretnél a későbbiekben valamiféle háttér-feldolgozást, adat exportot vagy hasonlót csinálni, ami böngészőből leginkább tákolás. Ezer meg egy oka lehet annak, hogy egy programot ne a HTTP interfészen keresztül szólíts meg. Ha akarsz interoperabilitást tesztelni, lőjj föl az Apache alá egy FastCGI-t és próbáld meg azon használni a programot. Ha nem fut, javítsd ki.

Ami a unittesztelést illeti, a unitteszt olyan, mint egy specifikáció. Amikor először láttam ilyet, én is nagyon elcsodálkoztam. Előbb írod meg a unittesztet, utána magát a programkódot. Így mindjárt előre tisztázod magadban, hogy mik is a követelmények. Ez egy érdekes szemléletváltás azzal szemben, hogy nekiállsz, kódolsz, működik valahogy, aztán mégis másképp kéne. Próbáld ki, érdemes.
12

Ki fogom, ne aggódj :D Azért

inf · 2010. Aug. 6. (P), 12.55
Ki fogom, ne aggódj :D Azért nekem is kell idő, hogy fejlődjek valahova.. :-) Jövő ilyenkor már csak TDD módszerrel fogok dolgozni...

CLI-n még gondolkodok, nem tudom hogy lehet megvalósítani, nincs tapasztalatom vele.

Alapból olyan rendszert szeretnék, aminek van SOA támogatása, szóval lehet, hogy inkább SOAP-pal fogom megszólítani a progit CLI helyett. Úgy könnyebb struktúráltabb adatot átadni.

Egyébként szinte kizárólag a soap miatt csinálok saját fw-t, van egy elképzelésem, hogy js hogyan tudna php-vel soap-pal kommunikálni, és szeretném megvalósítani. Leginkább az a része tetszik a dolognak, hogy a wsdl-ben megadott xsd-vel lehet automatikus validálást is csinálni a soapEnv-re, nem kell egyenként megnézni a változókat, hogy stimmel e a típusuk, és a típuskonverzió is automatikus. (A meló mondjuk sok vele, nem csak php, hanem js oldalról is. Normális soa-hoz kellenének osztályok, amiket js még nem támogat. Meg xsd-ben meg kell oldani, hogy le tudjam szűkíteni az átadott tulajdonságok körét a teljes osztályról. Igazából ez utóbbi a nehezebb, js-be osztályokat csukott szemmel is írok...)
13

Vigyázz vele

janoszen · 2010. Aug. 6. (P), 16.54
Vigyázz a SOAP interface-el, a PHP-é nagyon nagyon bugos és elég nagy az overheadje. És mint azt itt írta is valaki, az automatikus validálás, na az nem működik. :)
14

Tudom, én írtam :D Meg azt

inf · 2010. Aug. 6. (P), 19.42
Tudom, én írtam :D Meg azt hiszem pont te írtad már kétszer máshol, hogy gány az interface. :D
Olyasmit szeretnék, hogy megadom a wsdl-t, aztán az abban lévő alap XML Schema-ból generálom az adatbázist meg a DAO osztályokat, az alap séma szűkítésével meg az action paraméterek típusait határozom meg, és kigenerálom a serviceket.

Ez így lehet, hogy kicsit tömény lett. :D

Mondok példát, mondjuk a felhasználót beléptetjük:
bool UserService.login(UserDao<email,password> user);

az alap UserDao osztály:
UserDao<id,name,email,password,last_login ...>

az alap szűkítése, amit az UserService.login használ meg:
UserDao<email,password>

Itt az átadott UserDao xsd típusa eltér az alap UserDao xsd típusától, mert az átadottnál csak email és password példányváltozókat adhatjuk meg, ezt meg xsd-vel validáltatni kell. Úgy szeretném megoldani, hogy az alap típust részletesen megadom, a leszűkítést meg valami egyszerű módon csinálom meg az alap típust felhasználva. Viszont kicsi az esély, hogy ez ténylegesen megoldható, mert alapból nem jellemző ez a fajta megközelítés a programnyelvekre, szal valszeg az xsd-re sem lesz az. (Persze aztán ki tudja, lehet, hogy szerencsém lesz.)
15

Nem jo otlet.

janoszen · 2010. Aug. 7. (Szo), 12.39
Az alapvetoen nem jo otlet, hogy 1:1 megfeleltetest vonsz az adatbazisod es a SOAP interfesz koze. Lassuk, miert:

  • a SOAP interfesz lassu, a muveleteket ezert erdemes osszevonni, egyszerusiteni.
  • Az adatbazis szerkezet ismerete jelenthet security problemat (injection, lassu muveletek azonositasa utan DOS, stb.
  • Beszukited a jovobeni fejlesztesi lehetosegeidet.


Tudom, hogy manapsag mindenki kodot akar generalni, de egy vegig gondolt, az implementalo szemszogebol koherens interfesz sokkal jobb, mint a sajat szemszogedbol elsonek jonak tuno adatbazisbol lebutitott valtozat.
16

Bocs, elszabtam :D Dao

inf · 2010. Aug. 7. (Szo), 23.02
Bocs, elszabtam :D Dao helyett képzelj oda Model-t. Nyilván nem minden művelet használ adatbázist. Nyilván nem akarom, hogy 1 adatbázis kérésnek 1 http kérés feleljen meg, technikailag ez nem is igazán kivitelezhető bizonyos esetekben, meg hát van olyan kérés is, amikor nincs is szükség az adatbázisra, mondjuk ha védett fájlokat akarsz letöltetni....

Kicsit módosítok azon, amit írtam, valami olyasmit szeretnék, hogy xsd alapján építem fel az adatbázist, és ezt az xsd-t használom fel valamilyen formában a modeleknél és servicek (controllerek) felületét leíró wsdl-ben is. De nyilván a servicek felületéhez ennyi adatnál több fog kelleni....

Tisztában vagyok vele, hogy a Soap lassú, viszont azt is lehet kesselni ugyanúgy, mint bármilyen kimenetet. Előnyösnek meg elég előnyös, mert XML + XSLT -> XHTML, és ez már kliens oldalon is megy IE6-tól.
17

Hááát

janoszen · 2010. Aug. 8. (V), 07.59
A cachelhetőség attól függ, milyen adatokkal dolgozol. Üzleti alkalmazásnál pl. elfogadhatatlan, hogy nem aktuálisak az adatok.

A legfőbb érvem az automatikus API generálás ellen az API logikája. Olvasd el ezt, hátha jobba illusztrálja, amit mondani próbálok: http://lcsd05.cs.tamu.edu/slides/keynote.pdf

Update: szóval azt próbálom mondani, hogy szerintem, rossz oldalról közelíted meg. Az API felől kellene indulni a tervezéssel, mert ott merülnek föl a követelmények, nem az adatbázis oldalról. Az adatbázis a use casek következménye, nem oka.
18

Ahm, szóval nem biztos, hogy

inf · 2010. Aug. 9. (H), 05.34
Ahm, szóval nem biztos, hogy úgy kéne struktúrálni az adatokat, ahogy az adatbázisban vannak. Elolvasom a cikket, hátha meglátom a fényt... :D

szerk:
Hát tanulságos volt. :-) Egy részéhez gyenge volt az angolom, szótárazgattam. Tolódtam az először tervezés, aztán implementálás felé. Majd még elolvasom többször is.