• Acasă
  • Despre noi
  • Autori
  • Mărturii
  • Arhivă
  • Trimite Articol
  • Contact

WORLDIT

Lumea în 1 și 0.

  • Știri
    • Tehnologie
    • Tehnologie mobilă
    • Securitate
    • Developers
    • Știință
    • Benzi desenate
    • Jocuri
    • Intern
  • Tehnic
    • Browser
    • C#
    • C/C++
    • Challenge
    • HTML/CSS
    • Javascript, Ajax, jQuery
    • Open Source
    • PHP
    • Python
    • Securitate IT
    • Socializare
    • WordPress
    • Altele
  • Recenzii
  • Interviuri
  • Evenimente

Cum sa extragi parametrii unei functii in PHP?

6
  • Publicat de Andrei Avădănei
  • în PHP · Tehnic
  • — 11 iul., 2010 at 10:56 am

O problema destul de interesanta atunci cand vine vorba de interpretarea codului, este analiza parametrilor. In acest articol voi prezenta o modalitate, simpla, dar eficienta de a interpreta parametrii unei functii, clase initializate samd. Pentru a usura mai mult subiectul tratatat, am decis ca toti parametrii trebuie sa fie de tipul array(), de dimensiune nedefinita iar numarul acestora sa fie nelimitat.

Problemele intampinate

Evident, ca orice idee, aceasta poate avea „buguri”. Cel mai usor ar fi dupa unii sa rezolvam problema folosind o expresie regulata, sau un split dupa „,” samd. Nici una dintre aceste probleme nu poate fi abordata eficient pentru ca in primul caz, expresia regulata nu poate fi generalizata, iar in al doilea caz (problema care se aplica si la primul), virgula poate fi prezenta si in interiorul array-ului (daca acesta este unidimensional).

Abordarea corecta

Ideea care in aceasta situatie mi se pare cea mai eficienta, atat din punctul de vedere al complexitatii – O(n), cat si din punctul de de vedere al dificultatii de implementare este o abordare ce deriva dintr-un algoritm destul de simplu – evaluarea unei expresii in vederea corectitudinii ei.

Una din abordarile acestei probleme presupune numararea parantezelor deschise (adunarea lor) si eliminarea celor inchise (scaderea lor) atat timp cat acest lucru este posibil (valoarea respectiva depaseste zero). Modificand putin problema, vom avea urmatoarea abordare :

	function computeParams($params)
	{
		//O(n)
		$np   = array(); $open = 0; $content = ''; $i = 0; $n = strlen($params); $k = 0;
		while($i < $n) //cat timp indicele nu a depasit lungimea sirului
		{
                        //daca avem nevoie de un nou parametru, il cautam
			if($open <= 0 && stripos($params,'array(', $i) !== FALSE)
			{
                                //daca exista mutam indicele pe el, il initializam
				$i = stripos($params,'array(', $i)+5;
				$np[$k] = array();
				$open = 1; 
				$content = 'array(';
			}
			else //in caz contrar suntem intr-un indice ce incercam sa-l parcurgem
			{ 
				$content .= $params{$i}; // adaugam caracterul curent la parametrul actual(continutul acestuia)
				if($params{$i}=='(') $open++; // numaram parentezele deschise
				if($params{$i}==')') $open--; // scadem parantezele inchise 
				if($open <= 0) $np[$k++] = trim($content); // daca valoarea parantezelor este mai mica ca zero am terminat parametrul
			}			 
			$i++;
		}
		return $np;
	}

Ok, avem parametrii acum, intr-un array de forma $ARR[x] = tot continutul parametrului al x-lea. (indicele incepand de la zero).
Urmeaza interpretarea acestor parametri. Spre exemplu dorim sa avem $ARR[x][setare] = valoare. Din nou, pentru a simplifica codul, am decis ca toate valorile parametrilor sa fie de forma cheie => valoare. Vom avea nevoie de o noua functie.

	function computeParamsArgs($args)
	{
		//O(k + q) 
                //incercam sa gasim toti parametrii, folosind  expresia regulata de mai jos
		preg_match_all('/([\'"].*?[\'"]).*=>.*(array\(.*?\)|[\'"].*?[\'"]|true|false|0-9*)/is', $args, $args); //sizeof() = q
	 	
		$keys = $args[1]; //k = sizeof($keys), avem cheile parametrilor
		$vals = $args[2]; // avem valorile parametrilor
		$args = array();
		
                //parcurgem fiecare cheie 
		for($i = 0; $i < sizeof($keys); $i++)
		   if(isset($vals[$i])) //daca o gasim valoarea cheii respective	   			     
			   $args[trim($keys[$i],'\'" ')] = trim($vals[$i],'\'" '); // o parsam (fara ghilimele) si o adaugam intr-un vector
		return $args;
	}

Evident, abordarea de mai sus se refera doar la primul nivel al array-ului. Nu trebuie sa uitam faptul ca aceasta functie va fi folosita doar pentru a parsa unul dintre cei n parametrii extrasi. Interesanta poate fi si modificarea functiei, facand-o recursiva pentru a parsa un array in adancime. Oricum, editarea ei e o chestie de vreo 2-5 randuri, deci poate fi usor rezolvata daca esti interesat.

Ok, dar ce ne facem daca dorim sa restauram codul in forma lui originala? Pentru asta vom avea nevoie de o alta functie ce se va folosi de vectorul nostru unidimensional pentru a restaura parametrii intr-un singur sir.

    	private function restoreParamsArgs($args)
	{
		//O(2n)
		$params = 'array(';
						  
		foreach($args as $key => $value) //luam fiecare setare cu cheie/valoare 
		{
			if(strtolower(substr($value, 0, 6))!='array(' && strpos($value,'\'') !== false) //daca nu e un array valoarea
				$value = '\''.str_replace('\'', '\\\'', $value[$i]).'\''; //ii adaugam ghilimele, avand grija sa le parsam pe cele interioare
			$args[$key] = '\''.$key.'\' => '.$value; //adaugam argumentele intr-un vector sub forma de sir de caractere
		}
		$params .= implode(',', array_values($args)); /lipim argumentele create
		$params.= ')';
		return $params;
	}

Abordarea este simpla, doar ca si aceasta va necesita putina atentie din partea dumneavoastra in cazul in care veti dori sa parcurgeti array-urile in adancime pana la ultimul nivel.

Cum punem totul in miscare?

Simplu!!!

$params = "array('cheie' => 'valoare', 'cheie2' => 1000, 'cheie3' => array(valoare)), array('cheie2' => TRUE, 'cheie3' => FALSE)"; 
$ARR = computeParams($params); //construim parametrii (parsam)

foreach($ARR as $key => $value) //interpretam cheile si valorile din parametrii
    $ARR[$key] = computeParamsArgs($value);
print_r($ARR);
$ARR[0]['cheie'] = 'valoare_modificata'; //modificam o valoare

foreach($ARR as $key => $value) //restauram
    $ARR[$key] = restoreParams($value);
$params = implode(','$ARR);//construim textul initial avand un parametru modificat
echo $params;

Aceasta idee poate fi dusa la un nivel foarte mare, ajungand sa interpreteze adevarate blocuri de cod in acest mod. Totul tine de imaginatia ta. Enjoy! 🙂

Etichete: cum sa parsezi codulexpresii regulate in phpparsare cod in phpparsare parametri in phpPHPtutorial in php

— Andrei Avădănei a scris 1246 articole

Andrei scrie pe worldit.info din vara lui 2011. Este fondatorul Asociatiei Centrul de Cercetare in Securitate Informatica din Romania - CCSIR si coordoneaza DefCamp, cea mai importanta conferinta de securitate informatica & hacking din Europa Centrala si de Est. Andrei ofera in cadrul Bit Sentinel servicii de securitate informatica, penetration testing, security management, recuperarea de pe urma unui atac cibernetic, training-uri si workshop-uri.

  • Articolul anterior Quit Facebook Day sau cum poti pierde 30.000 de membrii
  • Articolul următor Bitdefender Quiz – Afla acum daca te descurci fara un antivirus

6 Comentarii

  1. Webila spune:
    iulie 11, 2010 la 11:25 am

    Buna,

    Iti recomand sa citesti documentatia de PHP referitoare la functiile eval(), func_num_args() si func_get_args(), iar pentru lucrul cu clase, informatiile legate de Reflection – se poate face mult mai usor cu ajutorul lor ceea ce acoperi tu in acest articol.

  2. Andrei Avadanei spune:
    iulie 11, 2010 la 12:02 pm

    Salut! Sa vedem daca ai dreptate. 🙂

    Documentatia despre recomandarile oferite de tine le voi sari pentru ca sunt familiar cu ce fac. Problema abordata aici nu cred ca ai inteles-o in totalitate, pentru ca eu m-am referit la extragerea parametrilor din codul unui fisier astfel : Tu ai un fisier sursa.php in care incepi sa iti extragi diverse definitii de forma :

    $x = new $y(parametru1, parametru2, parametru3 samd);

    Pentru asta, evaluand codul si extragand parametri asa cum ai sugerat tu vom avea de pierdut pentru ca in final va duce la evaluarea codului si posibilitatea alterarii unor informatii – de exemplu poate in momentul in care am evaluat linia de cod data exemplu mai sus, ea automat a facut niste modificari in fisiere, a actualizat o baza de date, a trimis niste informatii la un alt server samd, in principiu chestii care nu le doreai.

    Articolul a prezentat o modalitate eficienta de a intepreta codul citindu-l efectiv, si nu evaluandu-l, treaba care ar duce la probleme. 🙂

    Sper ca ai inteles la ce m-am referit. 🙂

  3. ant spune:
    iulie 12, 2010 la 1:01 am

    nu am inteles in practica la ce ar putea sa-mi foloseasca functiile prezentate… mi-ar prinde bine un exemplu concret… multumesc!

  4. Nicolae Vartolomei spune:
    iulie 12, 2010 la 1:03 am

    Redneckcode detected.

    Indus?

  5. Andrei Avadanei spune:
    iulie 12, 2010 la 2:25 am

    @Nicolae Vartolomei Cui i se adreseaza si ce vrea sa insemne? 🙂
    @ant Exemplu concret in practica (unde am avut eu nevoie de o astfel de abordare).

    Sa presupunem ca tu vrei sa intepretezi anumite parti de cod. Situatia de fata va cauta doar parametrii. Evident, ce am dat eu aici nu e tot codul, pentru ca asa ar fi floare la ureche.

    Sa presupunem ca dorim sa modificam fisierul x.php in mod dinamic(actualizand informatiile din el).

    Undeva, avem :

    $x = new $y(array('x' => 'y'));
    

    Cautand linia asta si folosindu-ne de prima functie pusa la dispozitie + a doua vom ajunge la un vector de forma :
    $ARR[0][‘x’] = y;
    Eu acum de exemplu, voi putea adauga un alt parametru : $ARR[0][‘p’] = 10 si voi restaura linia respectiva avand in fisier de acum

    $x = new $y(array('x' => 'y', 'p' => '10'));

    Problema e o chestie incipienta dintr-un viitor intepretor care il poti dezvolta chiar tu. 🙂

  6. Peste 20 de articole din 2010 ce merita citite de un programator web | WorldIT spune:
    decembrie 29, 2010 la 1:11 pm

    […] editare Afla cand cineva ti-a citit mailul Introducere in Design Patterns – MVC (1, 2 si 3) Cum sa extrageti parametrii unei functii in PHP? Cum sa extrageti numele unei variabile in PHP? Memcached – o solutie NoSQL Curl Multithread […]


  • Facebook

    WorldIT.info
  • Ultimele Atacuri Cibernetice din Romania – RO Hacked

    [wp_rss_retriever url="https://rohacked.bit-sentinel.com/feed/" excerpt="none" items="5" read_more="false" new_window="true" thumbnail="false" cache="0"] RO Hacked este registrul atacurilor cibernetice din România.
  • Caută

  • Articole Recomandate

    • Recent Posts
    • Tags
    • Număr record de participanți la DefCamp 2015, cel mai important eveniment dedicat securității cibernetice din Europe Centrala si de Estdecembrie 2, 2015
    • La DefCamp 2015 vei afla prin ce tehnici pot fi evitate măsurile de securitate ale sistemelor informatice criticeoctombrie 16, 2015
    • Ultima sansa sa rezervi bilete de tip Early Bird la DefCamp 2015septembrie 1, 2015
    • 15 sfaturi despre cum poti deveni un programator bun venite de la specialisti romaniaugust 4, 2015
    • algoritmica Android antivirus Apple Avadanei Andrei benzi desenate BitDefender blog browser C++ Chrome concurs eveniment Facebook Firefox Google google chrome hacking html5 infografic informatica internet Internet Explorer IT javascript linux Microsoft Mozilla Firefox online PHP programare retea sociala review Romania securitate Tehnologie Twitter web Windows Windows 7 Wordpress WorldIT worldit.info Yahoo! YouTube
  • februarie 2021
    L Ma Mi J V S D
    1234567
    891011121314
    15161718192021
    22232425262728
    « dec.    
  • Link-uri Sponsorizate

    • laptop second hand

    • Calculatoare Second Hand

    • cod voucher pc garage

  • Home
  • Tehnic
  • PHP
  • Cum sa extragi parametrii unei functii in PHP?
  • Important

    • Bit Sentinel
    • Centrul de Cercetare în Securitate Informatică din România
    • DefCamp
  • Prieteni

    • BetiT.ro
    • bijuterii handmade
    • Computerica | Resurse gratuite PC
    • Descopera.org
    • Gadgeturi si IT – Giz.ro
  • Prieteni

    • PC – Config
    • RO Hacked
    • Stiri IT

Copyright © 2009-2014 WORLDIT. Toate drepturile Rezervate.
Termeni și condiții | Contact | Licența Creative Commons