[PHP] OOP class met functies

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Cyw00d
  • Registratie: Januari 2006
  • Laatst online: 15-05 12:30
Hallo,

Ik ben even het e.e.a. aan het testen en ben pas begonnen met OOP.

Ik wil een class aan maken die vervolgend gevuld gaat worden door functies buiten de class om, zoals onderstaande:

<?php

public class UserN {
public $username;
public $rangerpoints;
}


function SetUser() {
$cyw00d = new UserN();
$cyw00d->username = "Cyw00d";
}

SetUser();

echo $cyw00d->username;

?>

Bovenstaande werkt dus niet, wel als ik de variable $cyw00d->username vul buiten de functie om, dan werkt het wel, iemand enig idee hoe ik dit werkend kan krijgen?

[ Tesla MIG MYP ]


Acties:
  • 0 Henk 'm!

  • Barryvdh
  • Registratie: Juni 2003
  • Laatst online: 21:42
Als je in die function SetUser() zit, heeft die zijn eigen scope. Je kan het object meegeven.

PHP:
1
2
3
4
5
6
7
function SetUser($user) {
    $user->username = "Cyw00d";
}

$cyw00d = new UserN();
SetUser($user);
echo $cyw00d->username;


Maar ik weet niet of dat is wat je wil bereiken?
(Tip, gebruik [ code] tags)

Acties:
  • 0 Henk 'm!

  • kamustra
  • Registratie: November 2006
  • Niet online
De variabele $cyw00d bestaat alleen binnen die functie.
De zoekterm die je nodig hebt is variable scope.
http://www.php.net/manual/en/language.variables.scope.php

Concreet in dit geval zou je het volgende kunnen doen:
PHP:
1
2
3
4
function SetUser() {
global $cyw00d = new UserN();
$cyw00d->username = "Cyw00d";
}

Of dat een goed idee is een tweede: die variable scope is niet voor niets zo dat de variabele enkel binnen de functie bestaat.

Een andere, betere, optie is je functie een waarde te laten teruggeven en die te gebruiken:
PHP:
1
2
3
4
5
6
7
8
function SetUser() {
$cyw00d = new UserN();
$cyw00d->username = "Cyw00d";

return $cyw00d
}

$cyw00d = SetUser();


Los daarvan heeft deze vraag weinig met OOP te maken: ook als je variabele een integer, string of wat dan ook was had je hetzelfde probleem. Dat dat nu toevallig een object is verandert daar niets aan.

Acties:
  • 0 Henk 'm!

  • Cyw00d
  • Registratie: Januari 2006
  • Laatst online: 15-05 12:30
Dat laatste heb ik nu geprobeerd, als ik daar "echo $cyw00d->username;" aan toevoeg geeft hij dus niets weer.

Nee klopt, ik kwam het probleem toevallig tegen nu ik met OOP aan het stoeien ben.

[ Tesla MIG MYP ]


Acties:
  • 0 Henk 'm!

  • Barryvdh
  • Registratie: Juni 2003
  • Laatst online: 21:42
Cyw00d schreef op woensdag 11 juni 2014 @ 18:54:
Dat laatste heb ik nu geprobeerd, als ik daar "echo $cyw00d->username;" aan toevoeg geeft hij dus niets weer.

Nee klopt, ik kwam het probleem toevallig tegen nu ik met OOP aan het stoeien ben.
Zit overigens wel een foutje in, hij is een ; vergeten na zijn return statement.
Maar ga je even inlezen in dat scope gebeuren, dan komt het vast goed ;)
En stel je error_reporting in dat je alles (ook waarschuwing) toont en je kan var_dump gebruiken om je object wat uitgebreider te bekijken en zien wat er veranderd.

Acties:
  • 0 Henk 'm!

  • kamustra
  • Registratie: November 2006
  • Niet online
Doe dan eens een print_r van $cyw00d? Dan kan je zien of het object goed is aangemaakt en of de propertie username goed is aangegeven. Dit kan je op verschillende plaatsen in je code doen, dan kan je precies volgen wat er wanneer gebeurt. (Natuurlijk enkel om te debuggen en het te leren, dat zet je nooit in je "echte" code)
Barryvdh schreef op woensdag 11 juni 2014 @ 18:59:
[...]

Zit overigens wel een foutje in, hij is een ; vergeten na zijn return statement.
Oeps, my bad. O-)

[ Voor 25% gewijzigd door kamustra op 11-06-2014 19:01 ]


Acties:
  • 0 Henk 'm!

  • Cyw00d
  • Registratie: Januari 2006
  • Laatst online: 15-05 12:30
Hebbes, ik ga even verder stoeien, bedankt! :)

[ Tesla MIG MYP ]


Acties:
  • 0 Henk 'm!

  • Rannasha
  • Registratie: Januari 2002
  • Nu online

Rannasha

Does not compute.

Gezien je met OOP bezig gaat, lijkt mij de netste aanpak om SetUser() als methode van de class UserN te definieren:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
public class UserN {
    public $username;
    public $rangerpoints;

    public function SetUser($un) {
        this->username = $un;
    }
}

$cyw00d = new UserN();
$cyw00d->SetUser("Cyw00d");

echo $cyw00d->username;


Heb al heel lang geen PHP meer gebruikt, dus mijn syntax is mogelijk niet 100% correct.

|| Vierkant voor Wiskunde ||


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 01-06 18:50

NMe

Quia Ego Sic Dico.

Rannasha schreef op woensdag 11 juni 2014 @ 21:56:
Gezien je met OOP bezig gaat, lijkt mij de netste aanpak om SetUser() als methode van de class UserN te definieren:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
public class UserN {
    public $username;
    public $rangerpoints;

    public function SetUser($un) {
        this->username = $un;
    }
}

$cyw00d = new UserN();
$cyw00d->SetUser("Cyw00d");

echo $cyw00d->username;


Heb al heel lang geen PHP meer gebruikt, dus mijn syntax is mogelijk niet 100% correct.
Komt in de buurt, maar nog steeds niet helemaal netjes. Je set namelijk geen user, maar een username. Omdat PHP properties mist maak je meestal zelf get- en set-methods aan. Direct members aanspreken wordt eigenlijk bijna altijd afgeraden, te meer omdat je door de het dynamische/zwakke karakter van types in PHP jezelf aardig in de voet kan schieten bij een foute toekenning.

Daarbij zou ik zo'n class niet UserN noemen maar een volledig uitgeschreven naam. Ik weet niet waar de N voor staat, maar als die niets betekent kun je hem beter weglaten, betekent hij wel wat, dan kun je beter uitschrijven wat hij betekent.

PHP heeft bovendien geen method overloading, dus meerdere verschillende constructors gaan niet zomaar. Omdat je zowel een lege user wil kunnen aanmaken en een user wil kunnen maken op basis van zijn naam zou je aan een static method kunnen denken, al zijn er ook andere oplossingen in de vorm van parameters met default values denkbaar.

Even puur dit simpele voorbeeldje beter uitwerken dus:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class User
{
    public function setUserName($userName)
    {
        $this->userName = $userName;
        return $this;
    }

    public function getUserName()
    {
        return $this->userName;
    }

    public static function createFromName($userName)
    {
        $user = new User();
        $user->setUserName($userName);
        return $user;
    }

    private $userName;
    private $rangerPoints = 0;
}

$cyw00d = User::createFromName("Cyw00d");
echo $cyw00d->getUserName();

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Cyw00d
  • Registratie: Januari 2006
  • Laatst online: 15-05 12:30
Bedankt voor de reacties, het is alleen zo dat ik buiten de class om ook functies gebruik voor andere zaken, ik wilde in die functies de class variabelen vullen.

Is het dan het beste om een functie in de class te maken, en die op te roepen in andere functies buiten de class om?

[ Tesla MIG MYP ]


Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Kun je iets concreter omschrijven wat je probeert te maken? NMe heeft je al een goed voorbeeld gegeven van hoe je een entiteit kunt aanmaken. Als je iets met die user wilt doen kun je op die klasse gewoon functies toevoegen, je user object ($cyw00d in dit geval) kun je heen en weer gooien en daarop die functies aanspreken.

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 01-06 18:50

NMe

Quia Ego Sic Dico.

Cyw00d schreef op woensdag 11 juni 2014 @ 22:20:
Is het dan het beste om een functie in de class te maken, en die op te roepen in andere functies buiten de class om?
SOLID helpt je een heel eind verder denk ik. In dit geval vooral de S; dat de andere 4 letters voor een beginner nog wat hoog gegrepen zijn geef ik meteen toe. ;)

Op zich is het trouwens wel mogelijk om procedureel programmeren en OOP te mixen maar ik zou dat zo weinig mogelijk doen.

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Lethalis
  • Registratie: April 2002
  • Niet online
Van alle code die hier staat, vind ik die van NMe de enige die goed leesbaar en logisch is (behalve dat foutje in getUserName dan :P daar hoort geen parameter meer te staan).

Rannasha ging even aan het data hiding principe voorbij, de functie van kamustra is zonder parameters erg beperkt bruikbaar en de code van Barryvdh druist tegen nogal wat OO principes in (wederom data hiding, maar ook functie die parameter verandert ipv nieuw object teruggeeft).

[ Voor 76% gewijzigd door Lethalis op 12-06-2014 09:00 ]

Ask yourself if you are happy and then you cease to be.


Acties:
  • 0 Henk 'm!

  • jbdeiman
  • Registratie: September 2008
  • Laatst online: 07:31
Lethalis schreef op donderdag 12 juni 2014 @ 08:53:
Van alle code die hier staat, vind ik die van NMe de enige die goed leesbaar en logisch is.

Rannasha ging even aan het data hiding principe voorbij en de functie van kamustra is zonder parameters erg beperkt bruikbaar.
Die van NME is de enige die het principe eigenlijk juist toepast, maar het vergt wel wat meer inzicht in het OOP ontwikkelen en vooraf e.e.a. goed uit proberen te denken.
Een "global" (ivm scope) is niet de juiste manier om e.e.a. toe te passen. Binnen het object zelf het object aanmaken, een waarde setten en het object weer returnen is ook niet helemaal de juiste manier. Beide opties werken, maar wijkt wel af van de ideeën van het OOP ontwikkelen.

Acties:
  • 0 Henk 'm!

  • Barryvdh
  • Registratie: Juni 2003
  • Laatst online: 21:42
Rannasha ging even aan het data hiding principe voorbij, de functie van kamustra is zonder parameters erg beperkt bruikbaar en de code van Barryvdh druist tegen nogal wat OO principes in (wederom data hiding, maar ook functie die parameter verandert ipv nieuw object teruggeeft).
Ik zei ook niet dat mijn code een goed OOP voorbeeld was, maar dat zijn scope niet correct was. Daarom vroeg ik ook wat hij wilde bereiken ;) Want hij vroeg dus specifiek om een class die door functies buiten die class aangepast worden.

Maar waarom zou je in OOP niet een object aan mogen passen? Normaal gesproken inderaad wel via een getter/setter, maar je kan toch prima een andere class hebben, die je een object meegeeft om bewerkingen op uit te voeren?

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 01-06 18:50

NMe

Quia Ego Sic Dico.

Lethalis schreef op donderdag 12 juni 2014 @ 08:53:
Van alle code die hier staat, vind ik die van NMe de enige die goed leesbaar en logisch is (behalve dat foutje in getUserName dan :P daar hoort geen parameter meer te staan).
Welk foutje? O-)
jbdeiman schreef op donderdag 12 juni 2014 @ 08:59:
[...]

Een "global" (ivm scope) is niet de juiste manier om e.e.a. toe te passen. Binnen het object zelf het object aanmaken, een waarde setten en het object weer returnen is ook niet helemaal de juiste manier. Beide opties werken, maar wijkt wel af van de ideeën van het OOP ontwikkelen.
Klopt wel, maar in PHP heb je zoals gezegd geen method overloading. Stel je wil een user ook kunnen afleiden van een ID dat je uit de database haalt of van een e-mailadres. Je hebt in PHP dan twee reële keuzes. Je kan de losse functies zelf aanroepen om je object te vullen, of je maakt static methods die een nieuwe instantie maken op basis van de ingevoerde gegevens en die instantie returnen. Dat laatste kan vooral handig zijn voor een functie als User::getById($id), welke bijvoorbeeld een User-object aanmaakt op basis van het record in de database dat ID 12 heeft. Het klopt dat in dit specifieke geval de User::createFromName($userName) niet heel handig is, maar bruikbaar kan het wel zijn. Er zijn echter wel voorbeelden van waar dat handig is, bijvoorbeeld de native method DateTime::createFromFormat($format, $time, $timezone). 9 van de 10 keer heb je genoeg aan de constructor van de class, de tiende keer doe je het met deze statische method. ;)

Voor de volledigheid voor de topicstarter, dit kan ook:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class User
{
    public function getId()                   { return $this->id; }
    public function setId($id)                { $this->id = $id; }

    public function getUserName()             { return $this->userName; }
    public function setUserName($userName)    { $this->userName = $userName; }

    public function getEmail()                { return $this->email; }
    public function setEmail($email)          { $this->email = $email; }

    private $id;
    private $userName;
    private $email;
}

$user1 = new User();
$user1->setName("Pietje");

$user2 = new User();
$user2->setId(12);

Uiteraard moet je je class waar nodig wel uitbreiden met validity checks, error handling, databasepersistentie, enz. Maar dat hangt van je requirements af en kan ik je zo dus niet uitleggen. :)
Barryvdh schreef op donderdag 12 juni 2014 @ 11:22:
[...]

Maar waarom zou je in OOP niet een object aan mogen passen? Normaal gesproken inderaad wel via een getter/setter, maar je kan toch prima een andere class hebben, die je een object meegeeft om bewerkingen op uit te voeren?
Je mag wel vanuit object A object B aanpassen, maar dan doe je dat doorgaans via de accessormethods, niet via de members zelf. Dus daar gebruik je gewoon de get/set-functies.

[ Voor 8% gewijzigd door NMe op 12-06-2014 11:38 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Caelorum
  • Registratie: April 2005
  • Laatst online: 21:08
Die waarbij je de $user object niet returned in de static function? (of zie ik het nou verkeerd?)

Acties:
  • 0 Henk 'm!

  • Barryvdh
  • Registratie: Juni 2003
  • Laatst online: 21:42
NMe schreef op donderdag 12 juni 2014 @ 11:36:
[...]

Je mag wel vanuit object A object B aanpassen, maar dan doe je dat doorgaans via de accessormethods, niet via de members zelf. Dus daar gebruik je gewoon de get/set-functies.
Dat zei ik toch ook :P (Maar dat miste inderdaad in het voorbeeldje, maar dat was alleen om de scope te illustreren)

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 01-06 18:50

NMe

Quia Ego Sic Dico.

Caelorum schreef op donderdag 12 juni 2014 @ 11:48:
[...]

Die waarbij je de $user object niet returned in de static function? (of zie ik het nou verkeerd?)
Oeps. :P

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Biersteker
  • Registratie: Juni 2009
  • Laatst online: 03-06 17:06
Waarom private en niet protected.? Ik zat een soortgelijk stukje te maken. Ik zat niet op te letten.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class player {
    private $name;
    private $gold = 100;
    
    public function __construct($name){
        $this->name = $name;
        }
    public function AddGold($x){
        $this->gold = $this->gold + $x; 
    }   
    public function RemoveGold($x){
        $this->gold = $this->gold - $x; 
    }
    public function MyGold() {
        return $this->gold;
    }
    public function MyName(){
        return $this->name;
    }    
}    
$player = New player('MyName');
echo $player->MyName;  //Returns 'MyName';
echo $player->MyGold; //100
$player->AddGold(10); //+10 
echo $player->MyGold; //110

[ Voor 2% gewijzigd door Biersteker op 12-06-2014 15:02 . Reden: koffiegebrek ]

Originally, a hacker was someone who makes furniture with an axe.

Pagina: 1