Tutorials
OOP: Objecten en References
Deze tutorial legt uit wat references zijn, en hoe je ze binnen PHP kunt toepassen.
Pagina 1
Waarom deze tutorial:
PHP'ers uitleggen wat de mogelijkheden zijn op gebied van references* en objecten binnen PHP. Indien de term 'object' te vaag voor je is, is dit beslist geen tutorial voor jou..
*) Een reference is variabele die verwijst naar een 'object'.
*) Een reference is variabele die verwijst naar een 'object'.
Pagina 2
Voorbereiding
Als voorbeeld maken we in deze tutorial gebruik van de class 'Client'.
<?
class Client
{
var $name; // Naam van de client
var $cash; // Saldo van de client
// Constructor
function Client($name, $cash= 0)
{
$this->name = $name;
$this->cash = $cash;
}
// Instellen van saldo
function setCash($cash)
{
$this->cash = $cash;
}
// Instellen van saldo
function setName($name)
{
$this->name = $name;
}
// Opvragen van saldo
function getCash()
{
return $this->cash;
}
// Opvragen van naam
function getName()
{
return $this->name ;
}
// ..
function toString()
{
return "" . $this->name . " heeft een saldo van € " . number_format($this->cash, 2) . "";
}
}
?>
<?
class Client
{
var $name; // Naam van de client
var $cash; // Saldo van de client
// Constructor
function Client($name, $cash= 0)
{
$this->name = $name;
$this->cash = $cash;
}
// Instellen van saldo
function setCash($cash)
{
$this->cash = $cash;
}
// Instellen van saldo
function setName($name)
{
$this->name = $name;
}
// Opvragen van saldo
function getCash()
{
return $this->cash;
}
// Opvragen van naam
function getName()
{
return $this->name ;
}
// ..
function toString()
{
return "" . $this->name . " heeft een saldo van € " . number_format($this->cash, 2) . "";
}
}
?>
Pagina 3
Wat is het nut van references
Bij het aanroepen van een functie worden de waarden van de opgegeven argumenten doorgaans 'gekopieerd' in de functie (dit is algemeen bekend lijkt me). Met een references wordt de waarde niet gekopieerd, maar wordt verwezen naar het oorspronkelijke object.
Het voordeel dat je hier mee kan behalen is dat je op verschillende plaatsen in je script kunt verwijzen naar het zelfde object.
Merk op dat in PHP 4 er alleen references gemaakt kunnen worden naar objecten; niet naar 'normale' variabelen. Mogelijk veranderd dit in de toekomst..
Het voordeel dat je hier mee kan behalen is dat je op verschillende plaatsen in je script kunt verwijzen naar het zelfde object.
Merk op dat in PHP 4 er alleen references gemaakt kunnen worden naar objecten; niet naar 'normale' variabelen. Mogelijk veranderd dit in de toekomst..
Pagina 4
(heen en weer) Kopieeren van een objecten
Vaak volstaat het heen en weer kopieren van objecten prima..
Een voorbeeld:
<?
// Een functie om 20 euro aan het saldo van een client toe te voegen
function addTwentyEuro($client)
{
$client->setCash($client->getCash() + 20);
print("<p>" . $client->toString() . "</p>"); // #1
}
$client = new Client("Pholeron", 100); // Maak een nieuwe client
addTwentyEuro($client); // Voeg 20 euro toe aan het saldo
print("<p>" . $client->toString() . "</p>"); // #2
?>
Probleem waar we in dit voorbeeld tegenaan lopen is dat in de functie addTwentyEuro() een kopie is ontstaan van het object. Het saldo wordt aangepast in de kopie (#1), maar niet in het origineel (#2).
Dit is eenvoudig te verhelpen met de volgende oplossing, die overigens nog steeds geen gebruik maakt van references (een beetje PHP'er had dit zelf kunnen bedenken (:
<?
// Een functie om 20 euro aan het saldo van een client toe te voegen
function addTwentyEuro($client)
{
$client->setCash($client->getCash() + 20);
print($client->toString()); // Print #1
return $client;
}
$client = new Client("Pholeron", 100); // Maak een nieuwe client
$client = addTwentyEuro($client); // Voeg 20 euro toe aan het saldo
print("<p>" . $client->toString() . "</p>"); // Print #2
?>
Als ik dit al kan, wat moet ik dan references?? Lees gewoon ff verder (:
Stel je hebt meerdere clienten waarop je handelingen wilt verrichten
<?
$clienten = array(new Client("Pholeron", 100), new Client("PHPHulp.nl", 75), ...);
// Zoek een client op in de array $clienten op basis van de naam
function getClient($name)
{
for($i = 0; $i < sizeof($clienten); $i++)
{
if(strcasecmp($clienten[$i]->getName(), $name) === 0)
{
return $clienten[$i]; // Geeft een KOPIE!! van het object terug
}
}
return null; // Gebruik bij 'geen object' liever een 'null' i.p.v. bijvoorbeeld een 'false' (of wat dan ook). Wordt in dit voorbeeld niet afgevangen.
}
// Een functie om 20 euro aan het saldo van een client toe te voegen
function addTwentyEuro($client)
{
$client->setCash($client->getCash() + 20);
print($client->toString()); // Print #1
return $client;
}
// Nu willen we aan de client 'PHPHulp.nl' 20 euro toevoegen..
$client = getClient('PHPHulp.nl"); // Zoek de client op
$client = addTwentyEuro($client); // Voeg 20 euro toe aan het saldo
?>
Omdat we echter een kopie hebben van de client en niet het origineel, moeten we als we het origineel gaan terugzoeken in de array $clienten en deze overschrijven. Al deze extra handelingen zijn echter zeer onwenselijk.. De oplossing: references (:
Een voorbeeld:
<?
// Een functie om 20 euro aan het saldo van een client toe te voegen
function addTwentyEuro($client)
{
$client->setCash($client->getCash() + 20);
print("<p>" . $client->toString() . "</p>"); // #1
}
$client = new Client("Pholeron", 100); // Maak een nieuwe client
addTwentyEuro($client); // Voeg 20 euro toe aan het saldo
print("<p>" . $client->toString() . "</p>"); // #2
?>
Probleem waar we in dit voorbeeld tegenaan lopen is dat in de functie addTwentyEuro() een kopie is ontstaan van het object. Het saldo wordt aangepast in de kopie (#1), maar niet in het origineel (#2).
Dit is eenvoudig te verhelpen met de volgende oplossing, die overigens nog steeds geen gebruik maakt van references (een beetje PHP'er had dit zelf kunnen bedenken (:
<?
// Een functie om 20 euro aan het saldo van een client toe te voegen
function addTwentyEuro($client)
{
$client->setCash($client->getCash() + 20);
print($client->toString()); // Print #1
return $client;
}
$client = new Client("Pholeron", 100); // Maak een nieuwe client
$client = addTwentyEuro($client); // Voeg 20 euro toe aan het saldo
print("<p>" . $client->toString() . "</p>"); // Print #2
?>
Als ik dit al kan, wat moet ik dan references?? Lees gewoon ff verder (:
Stel je hebt meerdere clienten waarop je handelingen wilt verrichten
<?
$clienten = array(new Client("Pholeron", 100), new Client("PHPHulp.nl", 75), ...);
// Zoek een client op in de array $clienten op basis van de naam
function getClient($name)
{
for($i = 0; $i < sizeof($clienten); $i++)
{
if(strcasecmp($clienten[$i]->getName(), $name) === 0)
{
return $clienten[$i]; // Geeft een KOPIE!! van het object terug
}
}
return null; // Gebruik bij 'geen object' liever een 'null' i.p.v. bijvoorbeeld een 'false' (of wat dan ook). Wordt in dit voorbeeld niet afgevangen.
}
// Een functie om 20 euro aan het saldo van een client toe te voegen
function addTwentyEuro($client)
{
$client->setCash($client->getCash() + 20);
print($client->toString()); // Print #1
return $client;
}
// Nu willen we aan de client 'PHPHulp.nl' 20 euro toevoegen..
$client = getClient('PHPHulp.nl"); // Zoek de client op
$client = addTwentyEuro($client); // Voeg 20 euro toe aan het saldo
?>
Omdat we echter een kopie hebben van de client en niet het origineel, moeten we als we het origineel gaan terugzoeken in de array $clienten en deze overschrijven. Al deze extra handelingen zijn echter zeer onwenselijk.. De oplossing: references (:
Pagina 5
References in het algemeen
Het magische symbool voor references is de & (ampersand).
Om een references te maken naar een object moet je de volgende code gebruiken:
<?
$client = new Client("Pholeron", 100);
$client_ref = &$client; // $client_ref verwijst nu naar het zelfde object als waar de variabele $client nu ook naar verwijst.
// Pas het saldo van de client aan
$client->setCash(0);
print("<p>" . $client->toString() . "</p>"); // Geeft 0
print("<p>" . $client_ref->toString() . "</p>"); // Geeft 0
// Pas het saldo van de client opnieuw aan
$client_ref->setCash(50);
print("<p>" . $client->toString() . "</p>"); // Geeft 50
print("<p>" . $client_ref->toString() . "</p>"); // Geeft 50
?>
Of we nu de $client of de $client_ref variabele gebruiken maakt (in dit voorbeeld) dus niet uit, ze maken allebei veranderingen in het zelfde object.
Let op: Een reference moet ÓF een verwijzing naar een object bevatten, ÓF de waarde 'null'. Mijn PHP Engine geeft waarschuwingen als ik bijv een 'false' wil toekennen aan een reference.
Om een references te maken naar een object moet je de volgende code gebruiken:
<?
$client = new Client("Pholeron", 100);
$client_ref = &$client; // $client_ref verwijst nu naar het zelfde object als waar de variabele $client nu ook naar verwijst.
// Pas het saldo van de client aan
$client->setCash(0);
print("<p>" . $client->toString() . "</p>"); // Geeft 0
print("<p>" . $client_ref->toString() . "</p>"); // Geeft 0
// Pas het saldo van de client opnieuw aan
$client_ref->setCash(50);
print("<p>" . $client->toString() . "</p>"); // Geeft 50
print("<p>" . $client_ref->toString() . "</p>"); // Geeft 50
?>
Of we nu de $client of de $client_ref variabele gebruiken maakt (in dit voorbeeld) dus niet uit, ze maken allebei veranderingen in het zelfde object.
Let op: Een reference moet ÓF een verwijzing naar een object bevatten, ÓF de waarde 'null'. Mijn PHP Engine geeft waarschuwingen als ik bijv een 'false' wil toekennen aan een reference.
Pagina 6
References als argument van een functie
Zo geef je een verwijzing naar een object mee als argument in een functie
<?
// Een functie om 20 euro aan het saldo van een client toe te voegen
function addTwentyEuro(&$client) // Maak geen kopie, maar een reference
{
$client->setCash($client->getCash() + 20);
print("<p>" . $client->toString() . "</p>"); // #1
// Omdat we met een references werken, is het originele object aangepast.
// Het is dus niet meer nodig het object te return'en.
}
$client = new Client("Pholeron", 100); // Maak een nieuwe client
addTwentyEuro($client); // Voeg 20 euro toe aan het saldo
print("<p>" . $client->toString() . "</p>"); // #2
?>
Zowel #1 als #2 hebben het zelfde resultaat.
<?
// Een functie om 20 euro aan het saldo van een client toe te voegen
function addTwentyEuro(&$client) // Maak geen kopie, maar een reference
{
$client->setCash($client->getCash() + 20);
print("<p>" . $client->toString() . "</p>"); // #1
// Omdat we met een references werken, is het originele object aangepast.
// Het is dus niet meer nodig het object te return'en.
}
$client = new Client("Pholeron", 100); // Maak een nieuwe client
addTwentyEuro($client); // Voeg 20 euro toe aan het saldo
print("<p>" . $client->toString() . "</p>"); // #2
?>
Zowel #1 als #2 hebben het zelfde resultaat.
Pagina 7
References als resultaat van een functie
Zo krijg je een reference naar een object vanuit een functie
<?
$clienten = array(new Client("Pholeron", 100), new Client("PHPHulp.nl", 75), ...);
// Zoek een client op in de array $clienten op basis van de naam
function &getClient($name) // Let op het & teken
{
for($i = 0; $i < sizeof($clienten); $i++)
{
if(strcasecmp($clienten[$i]->getName(), $name) === 0)
{
return $clienten[$i]; // Geeft nu een REFERENCE!! van het object terug
}
}
return null; // Geef een NULL terug!!, wordt in dit voorbeeld niet afgevangen.
}
// Een functie om 20 euro aan het saldo van een client toe te voegen
function addTwentyEuro(&$client)
{
$client->setCash($client->getCash() + 20);
print($client->toString()); // Print #1
}
// Nu willen we aan de client 'PHPHulp.nl' 20 euro toevoegen..
$client = &getClient("PHPHulp.nl"); // Zoek de client op (let op het & teken)
addTwentyEuro($client); // Voeg 20 euro toe aan het saldo
?>
Door een & voor de functie, Én voor de functie aanroep te zetten, krijg je een reference terug uit de functie.
Zet je geen & voor de aanroep, dan krijg je een 'normale' kopie.
Zet je geen & voor de functie (maar wel voor de aanroep), dan krijg je (bij mijn PHP engine) een waarschuwing.
<?
$clienten = array(new Client("Pholeron", 100), new Client("PHPHulp.nl", 75), ...);
// Zoek een client op in de array $clienten op basis van de naam
function &getClient($name) // Let op het & teken
{
for($i = 0; $i < sizeof($clienten); $i++)
{
if(strcasecmp($clienten[$i]->getName(), $name) === 0)
{
return $clienten[$i]; // Geeft nu een REFERENCE!! van het object terug
}
}
return null; // Geef een NULL terug!!, wordt in dit voorbeeld niet afgevangen.
}
// Een functie om 20 euro aan het saldo van een client toe te voegen
function addTwentyEuro(&$client)
{
$client->setCash($client->getCash() + 20);
print($client->toString()); // Print #1
}
// Nu willen we aan de client 'PHPHulp.nl' 20 euro toevoegen..
$client = &getClient("PHPHulp.nl"); // Zoek de client op (let op het & teken)
addTwentyEuro($client); // Voeg 20 euro toe aan het saldo
?>
Door een & voor de functie, Én voor de functie aanroep te zetten, krijg je een reference terug uit de functie.
Zet je geen & voor de aanroep, dan krijg je een 'normale' kopie.
Zet je geen & voor de functie (maar wel voor de aanroep), dan krijg je (bij mijn PHP engine) een waarschuwing.
Pagina 8
Samenvatting
- References zorgen er voor dat je eenzelfde object vanuit verschillende 'variabele' kunt benaderen. Met name als een object als argument van een functie dient, is het makkelijk om reference te gebruiken.
- References kunnen alleen gemaakt worden naar objecten. (nog) niet naar 'normale' variabelen.
- Het 'magische teken' voor references is de & (ampersand).
Voorbeelden van references:
<?
function myfunc(&$object) // & = Maak geen kopie maar een reference naar het object
{
// ..
}
function &myfunc2() // & = Geef geen kopie maar een reference terug
{
// .. geef een object, ÓF 'null' terug!!
}
$object = new Object(); // Nieuw object
$object_pointer = &$object; // & = Maak een reference naar de variabele achter '$object'.
myfunc($object);
$object2 = &myfunc2(); // & = Bevestig dat je een reference wil, en geen kopie
$object3 = myfunc2(); // Toch een kopie i.p.v. een reference
?>
Succes! (:
- References kunnen alleen gemaakt worden naar objecten. (nog) niet naar 'normale' variabelen.
- Het 'magische teken' voor references is de & (ampersand).
Voorbeelden van references:
<?
function myfunc(&$object) // & = Maak geen kopie maar een reference naar het object
{
// ..
}
function &myfunc2() // & = Geef geen kopie maar een reference terug
{
// .. geef een object, ÓF 'null' terug!!
}
$object = new Object(); // Nieuw object
$object_pointer = &$object; // & = Maak een reference naar de variabele achter '$object'.
myfunc($object);
$object2 = &myfunc2(); // & = Bevestig dat je een reference wil, en geen kopie
$object3 = myfunc2(); // Toch een kopie i.p.v. een reference
?>
Succes! (:
Reacties
0