aan alle goede dingen komt een eind, webmasterplein.net 2003 - 2013
wij danken jullie voor al mooie momenten die dankzij dit forum ontstonden - Derk, Rutger en Stef

[php] By reference

Deel alles wat je delen kan, gebruik het voor opslag, plaats het omdat je er trots op bent of creëer samen wat moois!

[php] By reference

Berichtdoor Rik » 13 apr 2008 17:10

Iets wat nog niet veel mensen weten/gebruiken, maar al heel lang in PHP zit:
Code: Selecteer alles
<?php
// By value
$a = 20;
$b = $a;
$b = 10;
echo $a; // Output: 20

// By reference
$a = 20;
$b = &$a;
$b = 10;
echo $a; // Output: 10
?>

Het kan op allerlei plaatsen.
Code: Selecteer alles
<?php function foo(&$bar) {} ?>
Avatar gebruiker
Rik
wmpr
 
Berichten: 1576
Geregistreerd: 11 jun 2005 17:59

Re: [php] By reference

Berichtdoor frizzy » 13 apr 2008 17:20

Ik kende het al, maar waar is het precies handig voor?
frizzy
wmpr
 
Berichten: 4261
Geregistreerd: 20 sep 2006 16:03
Woonplaats: Boskoop :D

Re: [php] By reference

Berichtdoor Dark Inca » 13 apr 2008 17:52

Vooral bij functies kan het handig zijn.
Maar ik kende het ook al :)

Code: Selecteer alles
function foo($a){
    
$a++;
}
function
bar(&$a){
    
$a++;
}
$a = 2;
foo($a); // no reference
echo $a;
// echoes 2
bar($a); // reference
echo $a;
// echoes 3    
Dark Inca
wmpr
 
Berichten: 8
Geregistreerd: 08 apr 2008 22:26

Re: [php] By reference

Berichtdoor ElbertF » 13 apr 2008 18:40

Je kan inderdaad in een functie een waarde wijzigen van een variabele zonder deze global te maken of the returnen. Ik kan niet zeggen dat ik hetvaak gebruik, het grote voordeel heb ik nog niet zo gevonden.
Avatar gebruiker
ElbertF
wmpr
 
Berichten: 1310
Geregistreerd: 14 nov 2007 22:09

Re: [php] By reference

Berichtdoor libia » 14 apr 2008 17:08

het is volgensmij ook mogelijk om bijv. zoiets te doen:
Code: Selecteer alles
<?php
class foo
{
    protected
$a;
    function
__construct()
    {
        
$this->a = 0;
    }
    function
bar($a)
    {
         
$this->a = $a;
    }
    function
get()
    {
        return
$this->a;
    }
}
$a = 2;
$b = new foo();
$b->bar($a);
$c = new foo();
$c->bar(&$a);
$a = 5;
echo
$b->get(); //2
echo $c->get(); //5
?>

dit is geloof ik goed, maar ik kan iets fout gedaan hebben (of het gewoon helemaal fout hebben)
Avatar gebruiker
libia
wmpr
 
Berichten: 4149
Geregistreerd: 23 okt 2005 14:14
Woonplaats: Alphe!!

Re: [php] By reference

Berichtdoor ElbertF » 14 apr 2008 17:18

En nu een praktisch voorbeeld waarbij deze mogelijkheid onmisbaar is..? :?
Avatar gebruiker
ElbertF
wmpr
 
Berichten: 1310
Geregistreerd: 14 nov 2007 22:09

Re: [php] By reference

Berichtdoor libia » 14 apr 2008 19:46

als je mijn klasse uitwerkt, krijg je net als bij mysqli->bind_param dat je na het aanroepen van de functie de variabele nog kunt veranderen
zij zetten dan alleen de referentie in de functie.. dan zal het zoiets worden:
Code: Selecteer alles
<?php
class foo
{
    protected
$a;
    function
__construct()
    {
        
$this->a = 0;
    }
    function
bar(&$a)
    {
         
$this->a = $a;
    }
    function
get()
    {
        return
$this->a;
    }
}
$a = 2;
$b = new foo();
$b->bar($a);
echo
$b->get(); //2
$a = 5;
$b->get(); //5
?>
Avatar gebruiker
libia
wmpr
 
Berichten: 4149
Geregistreerd: 23 okt 2005 14:14
Woonplaats: Alphe!!

Re: [php] By reference

Berichtdoor Remi » 15 apr 2008 15:38

ElbertF schreef:En nu een praktisch voorbeeld waarbij deze mogelijkheid onmisbaar is..? :?

Het komt oorspronkelijk uit progameertalen zoals C. Waarbij je dan verwijst naar hetzelfde stukje geheugen. In plaats van het copieren van het stukje geheugen naar een nieuw stukje geheugen.
Onder php is er weinig nut voor, mss zijn er mensen die met c enzo hebben gewerkt en dat fijn vonden in php. Ik zou het niet weten.
Avatar gebruiker
Remi
wmpr
 
Berichten: 3010
Geregistreerd: 04 apr 2006 15:22

Re: [php] By reference

Berichtdoor DoubleJ » 19 apr 2008 11:15

frizzy schreef:Ik kende het al, maar waar is het precies handig voor?

Wat dacht je van 'performance'?

Stel je hebt een 'forum' ofzo iets.
En in je posting heb je dus een textarea.

Stel je hebt een functie genaamd 'process_post($post)' die je post aanpast voor je db, neem het volgende voorbeeld:
Code: Selecteer alles
<?php

$post_content
= $_POST['very_big_post_content'];

function
process_post($post_content)
{
    do_ugly_stuff_to_post($post_content);
    return $post_content;
}

$post_content = process_post($post_content);

insert_post($post_content);
?>

Wat gaat hier gebeuren, de $post_content wordt opgehaald, post content wordt 'gecopieerd', en dan verwerkt, en dan wordt de copy terug gestopt.

Dit houd kortweg in, dat je de $post_content twee keer in je geheugen hebt staan. Voor een kleine post maakt dit verder niet uit, op je webhost heb je minimaal 8MB geheugen voorje script dus dat zou makkelijk moeten passen.

Echter wanneer iemand een beetje langdradig gaat worden met zijn post, zou het zo maar kunnen dat je opeens iemand hebt die een post van 2MB plaatst(je weet het niet). Dan kopieer je deze post weer met de functie en hoppa -> 4MB van de 8 heb je al vol zitten. dat plus nog eventueel de rest van je script en al gauw heb je een out of memory error.

Dit kan soms niet helemaal wenselijk zijn(zeker bij embedded software, waar je ZEER beperkt geheugen hebt soms. Dus wat gaan we doen, we gaan een reference maken:
Code: Selecteer alles
<?php

$post_content
= $_POST['very_big_post_content'];

function
process_post(&$post_content)
{
    do_ugly_stuff_to_post($post_content);
    return $post_content;
}

process_post($post_content);

insert_post($post_content);
?>

Wat er nu gebeurd is dat de pointer die naar je geheugen locatie van de 2MB post wijst wordt doorgegeven.
Dus je post wordt niet gecopieerd, wat weer resulteerd in minder geheugen gebruik, dus betere performance.

Dat is 1 ding wat heel handig kan zijn met references.

Een andere is het volgende.
Een functie is in principe in staat om maar één waarde terug te geven, maar soms is het wenselijk om de functie meerdere waardes te laten wijzigen.
Voorbeeldje weer:
Code: Selecteer alles
<?php

function process_vars($a, $b, $c)
{
    $a = $b + $c;
    $c = $a + $b;
    $b = $c + $a;
    
    return $a
;
}

$a = 4;
$b = 2;
$c = 8;

$a = process_vars($a, $b, $c);
echo
$a; // Output = 10;
echo $b; // Output = 2;
echo $c; // Outpu = 8;
?>

In bovenstaande functie voeren we allemaal leuke dingen met A en B uit, maar nadat de functie is geweest, zijn $b en $c weer in hun oorspronkelijke waarde, passen we de formule echter aan met references dan krijgen we het volgende:
Code: Selecteer alles
<?php

function process_vars($a, &$b, &$c)
{
    $a = $b + $c;
    $c = $a + $b;
    $b = $c + $a;
    
    return $a
;
}

$a = 4;
$b = 2;
$c = 8;

$a = process_vars($a, $b, $c);
echo
$a; // Output = 10;
echo $b; // Output = 22;
echo $c; // Outpu = 12;
?>

De waardes van B en C zijn ook gewijzigd.

Goed, tot zover weer mijn bijdrage.
De wondere wereld van het wijde web.
Avatar gebruiker
DoubleJ
wmpr
 
Berichten: 253
Geregistreerd: 20 jan 2008 20:32

Re: [php] By reference

Berichtdoor ElbertF » 19 apr 2008 11:36

Kijk daar hebben we wat aan. :) Maar wat is het verschil met global? Daar bereik je hetzelfde mee..

Code: Selecteer alles
function process_vars($a, $b, $c)
{
    global $b, $c;

    $a = $b + $c;
    $c = $a + $b;
    $b = $c + $a;
    
    return $a
;
}  
Avatar gebruiker
ElbertF
wmpr
 
Berichten: 1310
Geregistreerd: 14 nov 2007 22:09

Re: [php] By reference

Berichtdoor Remi » 19 apr 2008 15:21

Er zit nog steeds een groot verschil tussen, ik zal zo ff een voorbeedlje maken/opzoeken. ;)

Het geheugen gebruik zit dan als nog anders in elkaar, ik kan alleen nu ff gaan progje aan de praat krijgen voor het teken van het geheugen. :|
Avatar gebruiker
Remi
wmpr
 
Berichten: 3010
Geregistreerd: 04 apr 2006 15:22

Re: [php] By reference

Berichtdoor Dark Inca » 19 apr 2008 19:52

ElbertF schreef:Kijk daar hebben we wat aan. :) Maar wat is het verschil met global? Daar bereik je hetzelfde mee..

Code: Selecteer alles
function process_vars($a, $b, $c)
{
    global
$b, $c;

    
$a = $b + $c;
    
$c = $a + $b;
    
$b = $c + $a;
    
    return
$a;
}    



heel simpel:

Code: Selecteer alles
<?php
function process_vars($a, $b, $c)
{
    global
$b, $c; // both doesn't exist so = 0

    
$a = $b + $c;// $a =  0+0
    
$c = $a + $b;// $c =  0+0
    
$b = $c + $a;// $b =  0+0
    
    
return $a; //  0
}

$test1 = 1;
$test2 = 2;
$test3 = 3;

$test1 = process_vars($test1, $test2,$test3);

echo
$test1. "<br />" . $test2 . "<br />" . $test3 . "<br />";
// echoes 0 2 3


function process_vars2(&$a, &$b, &$c)
{
    
$a = $b + $c;// $a = 2+3 = 5
    
$c = $a + $b;// $c = 5+2 = 7
    
$b = $c + $a;// $b = 7+5 = 12
}

$test1 = 1;
$test2 = 2;
$test3 = 3;
process_vars2($test1, $test2,$test3);

echo
$test1. "<br />" . $test2 . "<br />" . $test3 . "<br />";
// echoes 5 12 7


Hier zie je duidelijk dat het "by reference" veel makkelijker is.
Je zit dus niet vast aan bepaalde variablen.
Dark Inca
wmpr
 
Berichten: 8
Geregistreerd: 08 apr 2008 22:26

Re: [php] By reference

Berichtdoor DoubleJ » 22 apr 2008 18:38

Nog een puntje met globals, wat naar mijn idee wat minder opgaat met globals is het volgende:

Dit is even een C voorbeeldje, maar hiermee kan ik beter illustreren wat ik bedoel, verder de opmerking dat dit niet 'correct' c is, ik moet eerst de functies voordefinieren en variabelen enzo, maar het gaat hier even om het idee.
Code: Selecteer alles
#include <stdio.h>

// Globals
int a;
int b;
int c;

int main()
{
   initiate_stuff();
   // do more.
   return 0;
}
int initiate_stuff()
{   
   int a;
   int b;
   int c;
   
   a = 1;
   b = 2;
   c = 3;
   
   a = do_stuff(a, b, c);
   // Hier komt uit: a = 16, b = 7, c = -11
   printf("a = %d, b = %d, c = %d", a, b, c);
}
int do_stuff();
{
   a = do_more_stuff(b);
   a += c;
   b += c;
   c -= a;
   return a;
}

int do_more_stuff(int d);
{
   int result;
   
   result = c * d;
   c = c + d;
   return result + c;
}

Bovenstaande code is met globale variabelen a, b en c

Het volgende voorbeeld is zonder globale variabelen:
Code: Selecteer alles
#include <stdio.h>

int main()
{
   initiate_stuff();
   // do more.
   return 0;
}

int initiate_stuff()
{   
   int a;
   int b;
   int c;
   
   a = 1;
   b = 2;
   c = 3;
   
   a = do_stuff(a, b, c);
   // Hier komt uit: a = 16, b = 7, c = -11
   printf("a = %d, b = %d, c = %d", a, b, c);
}
   
int do_stuff(a, &b, &c);
{
   a = do_more_stuff(c, b);
   a += c;
   b += c;
   c -= a;
   return a;
}

int do_more_stuff(&c, d);
{
   int result;
   
   result = c * d;
   c = c + d;
   return result + c;
}

In bijde situaties komt er hetzelfde uit(anders heb ik een puzzelfoutje gemaakt).
Nu dan het antwoord op jouw vraag elbertF, WAAROM geen globale variabelen.

Nou het antwoord is simpel,
Stel dat ik na het aanroepen van de functie initiate_stuff() a, b en c niet meer gebruik.
In het geval van de globale variabelen, betekent dit dat ik nog wel steeds 3 Integer waarden in mijn geheugen blijf houden, die ik niet meer gebruik wat zonde is van je geheugen gebruik.
In voorbeeld nummer 2, ben ik na initiate_stuff() mijn variabelen 'kwijt' en is het geheugen op die plaatsen dus weer vrij van gebruik.

Nou is de manier waarop ik dit nu illustreer een beetje omslachtig, maar daar heb het dus wat mee te maken.

Hoop hiermee meer TLbuis licht op het onderwerp te hebben gegooit.
Globals zijn handig, alleen nemen ze vaste resources in, waardoor het niet altijd gewenst is om dit te hebben.

een mooi voorbeeldje is bijvoorbeeld de generate_text_for_storage() functie van phpBB, daar heb je ook de references naar de $uid, $bitfield en $options, nadat je die eenmaal in je DB hebt geplaatst wil je ze niet meer gebruiken, zouden de 'global' zijn dan blijf je de resources behouden.

{EDIT/TOEVOEGING}
Daarnaast is het bij globals zo, dat je vast zit aan het gebruik van een vaste variabele naam.
De wondere wereld van het wijde web.
Avatar gebruiker
DoubleJ
wmpr
 
Berichten: 253
Geregistreerd: 20 jan 2008 20:32


Keer terug naar Snippets



cron