ugrás a tartalomhoz

Php- függvény hívása a megadott kontextusban

inf · 2009. Nov. 19. (Cs), 01.20
Sziasztok!

Egy függvényt szeretnék meghívni egy objektum kontextusában, vagy átadni neki másik kontextusból adatot.
(kontextus=scope, jobb fordítást nem találtam)

Egyelőre az egyedüli működő megoldás a $GLOBALS használata, ill. php4 alatt létezik olyan, hogy aggregate, viszont nekem php5-ös megoldásra van szükségem.

Tud valaki ilyet?
 
1

Ideiglenes

inf · 2009. Nov. 19. (Cs), 02.57
Egyelőre csinálok egy összekötő osztályt a függvénynek, aminek a konstruktorában megadom a kontextust, mint paramétert, a függvényben pedig erre a paraméterre hivatkozom. Ennek elég nagy hátránya, hogy csak a public dolgokat lehet elérni az adott kontextusban.
2

Példa

gphilip · 2009. Nov. 19. (Cs), 17.08
Hali!

tudnál példát Írni, nem egészen értem. Biztosan van megoldás vagy design pattern erre, pl observer, ha jól gondolom, mit szeretnél.
3

Huhh

inf · 2009. Nov. 28. (Szo), 07.03
Hát nem tudom javascripthez mennyire értesz.

Javascriptben leírva kb ennyit szeretnék megcsinálni phpben:

<script>
Function.prototype.bind=function (scope)
{
	var method=this;
	return function ()
	{
		return method.apply(scope,arguments);
	};
};


var Class=Function;
Class.prototype.Create=function (params)
{
	var Class=function ()
	{
		if (typeof this.initialize=="function")
		{
			this.initialize.apply(this,arguments);
		}
	};
	
	for (var param in params)
	{
		Class.prototype[param]=params[param];
	}
	
	return Class;
};

var Template=Class.Create(
{
	initialize: function (data)
	{
		this.data=data;
	},
	evaluate: function (code)
	{
		eval(code);
	}
});



var Tree=Class.Create(
{
	initialize: function (tree)
	{
		this.tree=tree;
	},
	showRecursive: function (branches,showBranch,showLetter)
	{
		var resultString="";
		for (var i=0,l=branches.length; i<l; ++i)
		{
			var branch=branches[i];
			var isLetter=!("branches" in branch) || 
				!(branch.branches instanceof Array) || 
				!branch.branches.length; 
			resultString+=isLetter
				?showLetter(branch)
				:showBranch(branch,
					this.showRecursive(branch.branches,showBranch,showLetter)
				);
		}
		return resultString;
	},
	show: function (showTree,showBranch,showLetter)
	{
		return showTree(this.showRecursive(this.tree.branches,showBranch,showLetter));
	}
});

window.onload=function ()
{
	new Template(
	{
		tree: 
		{
			branches:
			[
				{label: "branch-a",
					branches:
					[
						{label: "letter-a1"},
						{label: "letter-a2"},
						{label: "branch-a3",
							branches:
							[
								{label: "letter-a3x"},
								{label: "letter-a3y"}
							]
						}
					]
				},
				{label: "letter-b"},
				{label: "branch-c",
					branches:
					[
						{label: "letter-c1"},
						{label: "letter-c2"}
					]
				}
			]
		},
		config:
		{
			branch:{color: "brown"},
			letter:{color: "green"}
		}
	}).evaluate(
		"var container=document.createElement('div');"+
		"document.body.appendChild(container);"+
		
		"var showTree=function (tree)"+
		"{"+
			"return '<ol>'+tree+'</ol>';"+
		"};"+
		
		"var showBranch=function (branch,sub)"+
		"{"+
			"return "+
				"'<li>'+"+
					"'<span style=\"color: '+this.data.config.branch.color+'\">'+"+
						"branch.label+"+
					"'</span>'+"+
					"'<ul>'+"+
						"sub+"+
					"'</ul>'+"+
				"'</li>';"+
		"};"+
		
		"var showLetter=function (letter)"+
		"{"+
			"return "+
				"'<li>'+"+
					"'<span style=\"color: '+this.data.config.letter.color+'\">'+"+
						"letter.label+"+
					"'</span>'+"+
				"'</li>';"+
		"};"+
		
		"var html=new Tree(this.data.tree).show("+
			"showTree.bind(this),"+
			"showBranch.bind(this),"+
			"showLetter.bind(this)"+
		");"+
		
		"container.innerHTML=html;"
		
	);
};
</script>
A lényege, hogy kapok egy stringet a Template::evaluate-be, amit egy Compiler fordít be sablonkódról php-be. Na most nekem van egy Tree osztályom, amivel meg tudom jeleníteni egy fa tartalmát tetszőleges kinézetben úgy, hogy függvényeket adok át neki. A függvényeknek a Template aktuális példányára kell vonatkozniuk, mert onnan jönnek a konfigurációs, meg egyéb adatok. (Ez csak egy példa külső osztályok használatára sablonon belül...) A Tree::show összedobja a megadott függvények és a fa alapján a kimenetet. Gyakorlatilag ennyi.

Elnézést a stringes, összeadogatós gányolásért, igazából az a rész külön fájlban van php-ben, az az, amit a Compiler kidob, mint php kódot.

Ha nem érthető a dolog, akkor csak szólj, aztán megpróbálom elmagyarázni. :-D


Vázlatosan a lényeg, hogy van egy kódom, amit eval-al meghívok úgy, hogy a Template egy példányának a scope-jában van. Tehát a "this" az a Template egy példánya lesz, aminek már a this.adat változója tárol a adatokat. A kód egy része egy külső osztály: Tree példányosításával foglalkozik. A Tree-nek át kell adni a példányosításnál adatokat, majd a megjelenítéshez a kódban megadott függvényeket. A megjelenítéshez megadott függvényeknek a Template példányának a scope-jában kell futniuk, hogy azok is tudjanak elérni adatokat a this.adat-ból.
Azért van szükség erre a szerkezetre, mert a Compiler minden változó elérést this.adat['változó']-ra fordít le. Szóval ezzel sajnos nem lehet variálni. Nem akarom elmagyarázni, hogy miért nem, mert nagyon bonyolult, a lényeg, hogy a this.adat-ot nem lehet átírni a fordítóban, a fordítón kívül pedig nem szeretném átírni, mert az szintén bonyolult (bár kevésbbé, mint az előző), és gányolás.



Php-ban úgy oldottam meg, hogy létrehozok egy összekötő osztályt, aminek a függvényei lettek a showTree, showBranch, showLetter, a nevét meg a sablonban kell megadni. Az összekötő osztálynál a __get,__set és __call át lett írva, hogy a Template példányra hivatkozzon. Eztán csináltam egy példányt ebből az osztályból, amit szépen átadtam a Tree-nek, és ő nagy kegyesen meghívta a megjelenítő függvényeket rajta. Ami ebben a megoldásban zavaró, hogy minden ilyen külső feldolgozónál egy-egy új osztályt kell létrehoznom. Szal ahányszor meg akarom hívni a Tree megjelenítés részét, annyiszor kell új osztályt létrehoznom. Hálistennek nincs olyan sok külső dolog, viszont ez az egy hívás - egy osztály dolog nagyon zavar. Ezért próbáltam keresni valami megoldást a témára, de sajnos eddig még nem találtam. Php4-ben van olyan, hogy aggregate, az talán segítene, de php5-ben nem lehet használni.
4

Scope

Joó Ádám · 2009. Nov. 28. (Szo), 09.13
kontextus=scope, jobb fordítást nem találtam


Hatókör.
5

Kösz.

inf · 2009. Nov. 28. (Szo), 20.03
Köszi. :-)