Hoe kan ik er voor zorgen dat PHP een error geeft op een teveel aan parameters als ik een functie van een class aanroep ?
<?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');
?>
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:
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:
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.
?Onbekende gebruiker
03-04-2022 09:01
gewijzigd op 03-04-2022 09:04
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):
<?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:
<?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.
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.
?Onbekende gebruiker
05-04-2022 20:27
gewijzigd op 05-04-2022 20:50
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.