[php] Dynamische functie aanroep met default waarden

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Buur75
  • Registratie: December 2006
  • Laatst online: 10-04 15:21
Hoi. Ik wil een functie aanroepen met variabelen die eerder in een array zijn gestopt. Geen probleem, ware het niet dat de te aanroepen functie twee verplichte variabelen mee moet krijgen, en twee optionele variabelen mee mag krijgen, die, als ze niet bekend zijn, wel een default waarde on de functie moeten hebben. Vergeet die verplichte variabelen, want die kan ik gewoon van te voren even checken, maar het zit 'm in die optionele variabelen met default waarden...

Bijvoorbeeld deze functie:
PHP:
1
function addtext($title, $fieldname, $alert = '', $max = '60') { }


De variabelen komen bijvoorbeeld uit deze array:
PHP:
1
2
3
$myvars['title'] = "Mijn titel";
$myvars['fieldname'] = "titelveld";
$myvars['alert'] = "Vul een titel in";


Voor het gemak hebben de indexen van de array $myvars al dezelfde naam als de variabelen die aan de functie mee moeten gegeven, ook al is dat niet nodig, maar goed... Even die indexen naar echte variabelen omzetten:

PHP:
1
2
3
foreach($myvars as $key => $value) {
   $$key = $value;
}


Nu kan ik die functie natuurlijk gewoon zo aanroepen:
PHP:
1
addtext($title, $fieldname, $alert, $max)

Maar niet heus, want $max is nu niet gezet en heeft dus geen waarde, en wordt dus als lege variabele naar de functie gestuurd, waardoor $max in de functie niet 60 is, maar NULL! Kortom, in dit geval zou ik de functie zo moeten aanroepen:
PHP:
1
addtext($title, $fieldname, $alert)

Dan gaat het wel goed.

Dit is natuurlijk makkelijk op te lossen met een enkelvoudig if-else statement, maar wat nu als het om veel meer optionele variabelen gaat met default waarden? Of wat nu als $myvars['max'] wel is opgegeven en $myvars['alert'] weer niet?

De manier waarop ik de functie moet aanroepen is dus afhankelijk van welke variabelen zijn gezet. Hoe krijg ik dit voor elkaar? (Je kunt er vanuit gaan dat de verplichte variabelen altijd als eerste in het functie statement worden meegegeven...)

Acties:
  • 0 Henk 'm!

  • WouZz
  • Registratie: Mei 2000
  • Niet online

WouZz

Elvis is alive!

PHP:
1
2
3
foreach($myvars as $key => $value) {
   $$key = $value;
}
Check extract()

Maareh, waarom niet gewoon
PHP:
1
addtext($myvars)


Of, mocht je de orginele signature ook willen gebruiken, een wrapper functie aanmaken:
PHP:
1
addtextFromArray($myvars)

[ Voor 24% gewijzigd door WouZz op 25-03-2008 16:03 ]

On track


Acties:
  • 0 Henk 'm!

  • Buur75
  • Registratie: December 2006
  • Laatst online: 10-04 15:21
Bedankt voor die extract, die kende ik nog niet! _/-\o_
Maar wat moet er dan in die "wrapper functie" (?) allemaal gebeuren? Ik weet niet precies wat een wrapper functie is of wat het inhoudt :?

Acties:
  • 0 Henk 'm!

  • ppx17
  • Registratie: December 2007
  • Laatst online: 22-08 18:09
De waarden uit de array halen en de orginele functie daarmee aanroepen?

40D | 8 | 50 | 100 | 300


Acties:
  • 0 Henk 'm!

  • WouZz
  • Registratie: Mei 2000
  • Niet online

WouZz

Elvis is alive!

Dit is natuurlijk makkelijk op te lossen met een enkelvoudig if-else statement, maar wat nu als het om veel meer optionele variabelen gaat met default waarden? Of wat nu als $myvars['max'] wel is opgegeven en $myvars['alert'] weer niet?
Volgens mij moet je het eenvoudig houden en addtext() met een array aanroepen.

In addtext() doe je dat iest als
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function addtext($parameters)
{
  if(is_array($parameters))
  {

    if(isset($parameters['title']))
    {
      echo 'title = '.$parameters['title'];
    }

    if(isset($parameters['max']))
    {
      echo 'max = '.$parameters['max'];
    }
    else
    {
      echo 'max = 0';
    }
    
    // etc...
  }
}

[ Voor 5% gewijzigd door WouZz op 25-03-2008 16:35 ]

On track


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Lees je in vwb variabelen en hun scope, en de werking van arrays. Ik heb nog nooit in een topic op tweakers $$ om een geldige reden gebruikt zien worden, en dit is geen uitzondering. Neem maar als regel aan dat als je vertrouwt op $$, dat je constructie stinkt. :>

{signature}


Acties:
  • 0 Henk 'm!

  • Buur75
  • Registratie: December 2006
  • Laatst online: 10-04 15:21
@Voutloos: Welnee, werkt prima...
En offtopic trouwens...

[ Voor 4% gewijzigd door Buur75 op 25-03-2008 16:44 ]


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Ik weet dat het kan, maar _iedere_ ervaren PHP devver weet dat het bad practice is. Misschien wat offtopic, maar omdat $$ wel in de top 10 worst practices staat is het zeker het vermelden waard.

In 99.999% vd gevallen (en die andere 0.001% ben ik nog niet tegengekomen) geldt: $$ gebruik == gammel script.

[ Voor 22% gewijzigd door Voutloos op 25-03-2008 16:50 ]

{signature}


Acties:
  • 0 Henk 'm!

  • RAJH
  • Registratie: Augustus 2001
  • Niet online
In plaats van $$ kun je ook gebruik maken van een array. Je houd dan je vars bij elkaar en hebt dan veel minder kans op het overschrijven van vars.

Acties:
  • 0 Henk 'm!

  • jbweb
  • Registratie: Oktober 2004
  • Laatst online: 04-10-2023

jbweb

professional noob

Maar zoals ik hier begrijp is er dus geen enkele manier om meer dan één default waarde mee te geven aan een functie?

@Voutloos: ik voel me een beetje aangevallen door je "iedere ervaren developer" :'(
Misschien ben ik niet de beste programmer, maar ik wist ook niet dat dit worst practice was. Ik ben nu wel benieuwd naar je worst top 10, want ik ben hier immers ook om te leren, en niet om me aangevallen te voelen. Kom op met die top 10!

Als ik een leuke signature bedenk, zijn jullie de eerste die het weten


Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 16:36
Tuurlijk kan dat wel, met call_user_func_array()

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • Blaise
  • Registratie: Juni 2001
  • Niet online
Het is in dit geval juist handig dat je data in een array zit, omdat je een functie aanroept met meerdere optionele variabelen. Dan kan je zoiets als hieronder doen. Eventueel nog met een check of bepaalde verplichte variabelen zijn geset.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

$myvars = array(
    'title'     => 'Mijn titel',
    'fieldname' => 'titelveld',
    'alert'     => 'Vul een titel in'
);

function addtext($myvars) {

    $default = array(
        'title'     => '',
        'fieldname' => '',
        'alert'     => '',
        'max'         => 60
    );

    // Overschrijf default waardes
    $myvars = array_merge($default, $myvars);
}

?>


Ik heb vaak methodes met een heleboel optionele variabelen met een default waarde, bijvoorbeeld om spul in de database te stoppen. Dan is dit enorm handig.

Acties:
  • 0 Henk 'm!

Verwijderd

Blaise schreef op dinsdag 25 maart 2008 @ 17:08:
Het is in dit geval juist handig dat je data in een array zit, omdat je een functie aanroept met meerdere optionele variabelen. Dan kan je zoiets als hieronder doen. Eventueel nog met een check of bepaalde verplichte variabelen zijn geset.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

$myvars = array(
    'title'     => 'Mijn titel',
    'fieldname' => 'titelveld',
    'alert'     => 'Vul een titel in'
);

function addtext($myvars) {

    $default = array(
        'title'     => '',
        'fieldname' => '',
        'alert'     => '',
        'max'         => 60
    );

    // Overschrijf default waardes
    $myvars = array_merge($default, $myvars);
}

?>


Ik heb vaak methodes met een heleboel optionele variabelen met een default waarde, bijvoorbeeld om spul in de database te stoppen. Dan is dit enorm handig.
maar dit werkt je weer ontzettend tegen omdat je IDE niet weet welke parameters een functie verwacht, moet je elke keer dat je de functie wilt gebruiken weer opzoeken!

(voor de TS, indien je nog geen IDE gebruikt, dit kan je php schrijven een stuk versnellen :). kijk bijvoorbeeld eens naar Zend Studio (ontzettend groot en bloated voor jouw gebruik misschien, ook niet gratis, maar het is een ontzettend fijne omgeving om van alles in te doen, dus probeer het eens :)))

[ Voor 12% gewijzigd door Verwijderd op 25-03-2008 18:12 ]


Acties:
  • 0 Henk 'm!

  • Icelus
  • Registratie: Januari 2004
  • Niet online
PHP:
1
2
3
4
5
function addtext($title, $fieldname, $alert=null, $max=null)
{
   if ( $alert === null ) $alert = '';
   if ( $max === null ) $max = 60;
}

Developer Accused Of Unreadable Code Refuses To Comment


Acties:
  • 0 Henk 'm!

  • Tanuki
  • Registratie: Januari 2005
  • Niet online
Icelus schreef op dinsdag 25 maart 2008 @ 18:37:
PHP:
1
2
3
4
5
function addtext($title, $fieldname, $alert=null, $max=null)
{
   if ( $alert === null ) $alert = '';
   if ( $max === null ) $max = 60;
}
Daar hebben we is_null() voor.

PV: Growatt MOD5000TL3-XH + 5720wp, WPB: Atlantic Explorer v4 270LC, L/L: MHI SCM 125ZM-S + SRK 50ZS-W + 2x SRK 25ZS-W + SRK 20ZS-W Modbus kWh meter nodig?


Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 16:36
Voordat het topic nog verder verzandt in offtopic geneuzel (nofi) en de oplossing niet wordt gezien. Wat de topic starter wil kan dus met call_user_func_array:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
function testMe($a, $b = 'default') {
    return 'a:' .$a .', b:' .$b;
}

$test[1] = array('a','b');
$test[2] = array('a');

foreach($test as $key => $params) {
    echo $key .': ' .call_user_func_array('testMe', $params) ."\n";
}
//1: a:a, b:b
//2: a:a, b:default

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

De oplossing van T-MOB lijkt me het beste. Je gaat geen functie aanpassen alleen omdat je op een bepaalde plek de parameters in een array hebt staan. Daar is call_user_func_array juist voor bedoeld.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Buur75
  • Registratie: December 2006
  • Laatst online: 10-04 15:21
Nee dat werkt niet. Wat dacht je bijvoorbeeld van deze situatie:
PHP:
1
2
3
4
5
6
7
8
9
10
function testMe($a, $b = 'default', $c = 'default') {
    return 'a:'. $a .', b:'. $b .', c:'. $c;
}

$test[1] = array('a','c');

foreach($test as $key => $params) {
    echo $key .': ' .call_user_func_array('testMe', $params) ."\n";
}
//1: a:a, b:c, c:default

De variabelen in de array $test worden 1 voor 1 in de variabelen gestopt die aan de functie worden meegegeven en dat is natuurlijk niet de bedoeling. Niet zoals het moet dus.

Die array_merge oplossing van Blaise lost dit wel goed op. Maar inderdaad, dan moeten de namen van de indexen van de array wel gelijk zijn aan de namen van de variabelen binnen de functie, maar dat is in mijn geval geen probleem. Ik gebruik toch geen IDE...

Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 16:36
Buur75 schreef op woensdag 26 maart 2008 @ 11:01:
De variabelen in de array $test worden 1 voor 1 in de variabelen gestopt die aan de functie worden meegegeven en dat is natuurlijk niet de bedoeling. Niet zoals het moet dus.
Ach natuurlijk, ik zie het al, mijn glazen bol heeft nieuwe baterijen nodig :+ Maar goed bij de situatie die je schetst kan ik me niet voorstellen dat je hem nodig hebt. In een normale function call kun je namelijk ook geen parameters overslaan.
Voor de functionaliteit die je probeert te maken zou ik een object inzetten:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class TestMe {
  public $a;
  public $b = 'default';
  public $c = 'default';

  public function test() {
    return 'a:'. $this->a .', b:'. $this->b .', c:'. $this->c; 
  }
}
$test = new TestMe();
$test->a = 'a';
$test->c = 'c';
echo $test->test();
//a:a, b:default, c:c

Regeren is vooruitschuiven

Pagina: 1