te veel functie parameters

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Ad Fundum

Ad Fundum

29/03/2022 09:58:50
Quote Anchor link
Hoe kan ik er voor zorgen dat PHP een error geeft op een teveel aan parameters als ik een functie van een class aanroep ?

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
abstract class basis {
  protected function _fout($k) {
    trigger_error('Eigenschap "' . $k . '" van object "'
      . get_class($this) . '" bestaat niet of is niet publiek.');
  }
  function
__get(string $k) {$this->_fout($k);}
  function
__set(string $k, $v) {$this->_fout($k);}
}

class test extends basis {
  function
__construct() {}
}

$uit = new test('ik wil hier een error op');
?>
 
PHP hulp

PHP hulp

27/06/2022 17:53:18
 
Ivo P

Ivo P

29/03/2022 12:16:34
Quote Anchor link
je zou kunnen proberen:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

class test_extends basis
{
  function
__construct()
  {

     $numargs = func_num_args();
     if($numargs > 0) {
       throw new Exception('too many arguments');
     }
  }
}

new
test(1, 2, 3);  
?>


https://www.php.net/manual/en/function.func-num-args.php
 
Ozzie PHP

Ozzie PHP

29/03/2022 14:43:56
Quote Anchor link
Ik zou niet zo snel weten waarom je dit zou willen gebruiken, maar als je dan toch gebruikmaakt van een Basis class dan zou ik daar ook gebruik van maken.

Heb een voorbeeldje voor je gemaakt.
 
Ad Fundum

Ad Fundum

30/03/2022 08:55:14
Quote Anchor link
Goed idee van func_num_args(). Kan ik dat ook gebruiken in de base class voor elke functie?

Ik had ooit een functie met meerdere argumenten:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
<?php
class x {
 function
y(string $a, string $b) : self {}
}

?>

En na refactoren werd dat
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
<?php
class x {
 function
y(string $a) : self {}
}

?>

Maar ergens was ik vergeten de functie-call te wijzigen en bleef dit staan:
$x->y($a, $b); // geen error...
En toen bedacht ik me dat je in PHP altijd meer argumenten kan geven dan een functie aankan.
Het zou mooi zijn als dat vanuit de basisklasse kan worden opgelost, zodat mijn code meer strikt wordt.
Gewijzigd op 30/03/2022 08:56:41 door Ad Fundum
 
Ivo P

Ivo P

30/03/2022 10:13:35
 
Ozzie PHP

Ozzie PHP

30/03/2022 10:34:51
Quote Anchor link
Ad Fundum op 30/03/2022 08:55:14:
Goed idee van func_num_args(). Kan ik dat ook gebruiken in de base class voor elke functie?

Mja, even mijn vorige voorbeeld aangepast naar dit voorbeeld.

Maar eigenlijk moet je dit echt niet willen. Als je dit bij iedere functie-aanroep doet, zorgt dat voor veel onnodige controles en functie-aanroepen.

Ik zou zeggen, als je een functie achteraf wijzigt, zoek dan even waar die functie nog meer wordt gebruikt en pas 'm daar aan. Je bent nu een oplossing aan het bedenken voor iets wat zich in de praktijk ooit misschien een keertje voordoet, maar wat wel je code vertroebelt met vele extra controles en functie-aanroepen. Ik denk niet dat je dat moet willen.
 
Ad Fundum

Ad Fundum

30/03/2022 11:09:17
Quote Anchor link
OK, bedankt voor het meedenken.
Ik was al bang dat het moeilijk zou gaan, maar die SO-links helpen wel met
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<?php
if(func_num_args()>count(get_defined_vars())) throw new Exception('Too many args.');
?>

En de RFC (https://wiki.php.net/rfc/strict_argcount)
Gewijzigd op 30/03/2022 11:11:14 door Ad Fundum
 
Ozzie PHP

Ozzie PHP

30/03/2022 11:14:57
Quote Anchor link
Heb je mijn voorbeeld ook gezien?
 
Ad Fundum

Ad Fundum

30/03/2022 11:22:46
Quote Anchor link
Ja, dat heb ik gezien, en het is wat je zegt. PHP is er niet voor gemaakt, dus moet ik het niet willen.
Gewijzigd op 30/03/2022 11:23:34 door Ad Fundum
 
Ozzie PHP

Ozzie PHP

30/03/2022 11:42:22
Quote Anchor link
Ik denk dat dat inderdaad de enige juiste conclusie is. Overigens verbaast het me wel dat er geen warning wordt gegeven als er te veel argumenten worden meegegeven aan een functie. Wellicht is dat om dit soort dingen mogelijk te maken:

$rekenmachine = new Rekenmachine();
$rekenmachine->optellen(2, 5, 8, 34, 56, 104);
 
Ivo P

Ivo P

30/03/2022 14:25:05
Quote Anchor link
PHP heeft zelf ook dergelijke functies. bijvoorbeeld array_merge()

Daar mag je een aantal array's opgeven en die worden samengevoegd.

In de manual staat nu

array_merge(array ...$arrays): array

Maar een aantal PHP versies geleden was ...$array nog een onbekende syntax.
Daar kon je dus omheen door gewoon meerdere parameters mee te geven.
 
Willem vp

Willem vp

02/04/2022 13:10:45
Quote Anchor link
Ozzie PHP op 30/03/2022 11:42:22:
Ik denk dat dat inderdaad de enige juiste conclusie is. Overigens verbaast het me wel dat er geen warning wordt gegeven als er te veel argumenten worden meegegeven aan een functie.

Ik denk dat dat komt, omdat bij de ontwikkeling van PHP met een scheef oog naar Perl is gekeken.

Van oudsher werden in Perl de functie-parameters in een anonieme array doorgegeven:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
sub doe_iets
{
   my $param1 = shift;
   my $param2 = shift;
   my @other_params = shift;
}

doe_iets('met', 'deze', 'tekst');

In principe waren alle parameters optioneel; als je de functie aanriep met doe_iets('doms') dan werd alleen $param1 gevuld en bleven $param2 en @other_params undefined. Op zich heel flexibel, maar het heeft wel als nadeel dat het lastig was om verplichte parameters af te dwingen. Daar kon je weliswaar function prototypes voor gebruiken, maar die werkten toch net iets anders dan je zou verwachten, vooral als je een taal als C gewend was.

Eigenlijk pas sinds 2015 ondersteunt Perl dit wat beter middels de (vooralsnog experimentele feature) subroutine signatures:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
sub doe_een_beetje ($param1)
{
}
sub doe_iets_meer ($param1, $param2 = 42, @other_params)
{
}

Als je nu doe_een_beetje() aanroept met een verkeerd aantal parameters, krijg je een foutmelding. Bij doe_iets_meer() is $param1 verplicht, $param2 optioneel (met default-waarde 42) en @other_params slurpt alles op wat je verder nog aan parameters meegeeft.

PHP lijkt qua werking dus een beetje tussen de oudere en nieuwere Perl-versies te zitten.
Gewijzigd op 02/04/2022 13:14:19 door Willem vp
 
Ad Fundum

Ad Fundum

03/04/2022 09:01:44
Quote Anchor link
Dat je het niet moet willen betekent niet dat het niet kan. Als je er maar gek genoeg voor bent (reken mij even niet mee) kan je iets met deze vingeroefening (waarschuwing, het middel is erger dan de kwaal):
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
abstract class basis {
  protected $f = [];
  function
__call(string $n, array $a) {
    if (!isset($this->f[$n])) {trigger_error('Functie ' . $n . ' bestaat niet');}
    if ((new ReflectionFunction($this->f[$n]))->getParameters()
      !==
count($a)) {trigger_error('Parameteraantal onjuist');}
    call_user_func_array($this->f[$n], $a);
  }
}

class test extends basis {
  function
__construct() {
    $this->f = [  // functiedefinities vanaf hier
      'functie' => function (string $a) {
        print $a . PHP_EOL;
      }
    ];
  // tot hier
  }
}

$t = new test;
$t->functie('A', 'B');  // error
?>

Eerder had ik class test zonder ctor:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?php
class test extends basis {
  protected $f = [  // functiedefinities vanaf hier
    'functie' => function (string $a) {print $a . PHP_EOL;}
  ];
  // tot hier
}
?>

Maar dat geeft een Fatal error: Constant expression contains invalid operations.

Gerelateerde info: https://www.sitepoint.com/community/t/pass-func-get-args-to-another-method-or-an-object/34653/10
Gewijzigd op 03/04/2022 09:04:25 door Ad Fundum
 
Ozzie PHP

Ozzie PHP

03/04/2022 15:51:03
Quote Anchor link
Ad Fundum op 03/04/2022 09:01:44:
Dat je het niet moet willen betekent niet dat het niet kan.

Dat het kan had ik hier ook al laten zien. Maar je moet het inderdaad niet willen.
 
Ad Fundum

Ad Fundum

05/04/2022 20:27:22
Quote Anchor link
Sorry Ozzie, ik was niet specifiek genoeg. Een deel van de oplossing die ik zocht was dat de code voor de controle op parameters in een basisklasse zou zitten, waarna de controle geldt voor elke (niet één) functie van klassen die bouwen op de basisklasse. Want anders zou het echt onevenredig veel code kosten.

De enige oplossing die ik vond was niet geweldig. Anonieme functies in een array in combinatie met __call() werkt wel, maar ik ga er niet van uit dat m'n IDE het ook snapt, laat staan dat je iets kan met public, protected en private functies.
Gewijzigd op 05/04/2022 20:50:34 door Ad Fundum
 
Ozzie PHP

Ozzie PHP

06/04/2022 02:47:13
Quote Anchor link
Ad Fundum op 05/04/2022 20:27:22:
De enige oplossing die ik vond was niet geweldig. Anonieme functies in een array in combinatie met __call() werkt wel ...

Nou, het was in ieder geval wel een creatieve poging :-)
 
Ad Fundum

Ad Fundum

06/04/2022 08:58:59
Quote Anchor link
:-) Typisch gevalletje EWD340
"De competente programmeur [...] vermijdt slimme truuks als de pest."
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.