Ik was even aan het kijken hoe PHP 7 werkt op het huidige systeem wat ik aan het schrijven en alles werkt behalve dat ik een strict error krijg in mijn database classe.

Ik maak gebruik van een classe die PDO extend, en hang hieraan een custom PDOStatement class.
<?php
class Statement extends PDOStatement{
public function execute(...$args){
parent::execute();
}
}
class Database extends PDO{}
?>

De foutmelding hierop is:
Warning: Declaration of Statement::execute(...$args) should be compatible with PDOStatement::execute($bound_input_params = NULL) in /path/to/statement.php on line 90

Hoewel ik de foutmelding begrijp, en de error heb weggewerkt met:
<?php
public function execute($a = null, ...$args){
array_unshift($args, $a);
$i = 0;

foreach($args as $var){
if(is_array($var)){
foreach($var as $key => $val){
if(preg_match('/(.*)(:.*)/', $key, $matches)){
$this->bindValue($matches[2], $val, empty($matches[1]) ? PDO::PARAM_STR : $this->getParam($matches[1][0]));
} else {
throw new DatabaseException("Unsupported array index, expected a :named parameter.", self::EX_PARAM_MISMATCH);
}
}
} else {
$this->bindValue($i+1, $args[$i++]);
}
}

$this->dbh->rsl = parent::execute();
$this->dbh->sth = $this;

return $this;
}
?>
Deze fix is natuurlijk niet echt netjes, maar ik begrijp niet echt waar deze melding vandaan komt en of dit misschien wel eens een bug zou kunnen zijn aangezien het lijn nummer ook niet klopt.

Hoewel het probleem uiteindelijk door de functie naam komt, wilde ik hier alleen een andere gebruik methode aan vast makken zodat je in de code niet de hele tijd met array's hoeft te werken.

In PHP 6 had ik hier geen problemen aan, en strict error reporting stond ook aan.
Dit probleem had ik volgens mij niet in PHP 7 RC1 (draai nu op RC2).
Ik heb zelf php7 nog niet, maar heb er wel wat over gelezen, dus wat als je het zo doet:

<?php
public function execute(): array {
parent::execute();
}
?>
Waarom doe je dit?


<?php
    public function execute(...$args)
    {
        parent::execute();
    }
?>


Als een methode niets anders doet dan dezelfde methode van de parent aanroepen, dan kun je de methode namelijk beter weglaten.
DavY Blaat op 22/09/2015 08:00:37

Ik heb zelf php7 nog niet, maar heb er wel wat over gelezen, dus wat als je het zo doet:

<?php
public function execute(): array {
parent::execute();
}
?>

Dat is optioneel, hoeft niet.

Ward van der Put op 22/09/2015 09:25:10

Waarom doe je dit?


<?php
    public function execute(...$args)
    {
        parent::execute();
    }
?>


Als een methode niets anders doet dan dezelfde methode van de parent aanroepen, dan kun je de methode namelijk beter weglaten.

Dat is niet de code die ik gebruik, dit is een voorbeeld van de stuctuur van mijn classe en ook meteen de code die de foutmelding geeft zonder poespas.

De daadwerkelijke "execute" methode die ik gebruik is in het tweede stukje code met de "quick" fix.
Warning: Declaration of Statement::execute(...$args) should be compatible with PDOStatement::execute($bound_input_params = NULL) in /path/to/statement.php on line 90

Dat geeft precies aan wat er aan scheelt? Jouw spinoff is niet compatibel.

In de execute() van PDOStatement is de parameter $bound_input_params optioneel, in jouw variant is deze verplicht.

Ik ken de syntax "...$args" niet, maar als je er nu eens het volgende van maakt?
<?php
class Statement extends PDOStatement {
    public function execute($args=NULL) {
        parent::execute($args);
    }
}
?>
The syntax ...$args zit ook in PHP 6, en werkt fantastisch aangezien je ook niet meer met func_get_args() hoeft te werken.

<?php
function bar($...foo){
foreach($foo as $var){
echo $var;
}
}

foo('dit','is','een','voorbeeld'); // result: ditiseenvoorbeeld
foo(...['dit','is','array unpacking']); // result: ditisarray unpacking | hoewel dit natuurlijk niet logisch is, is het wel bruikbaar als foo() argumenten moet hebben.
?>

Jouw voorbeeld doet eigenlijk hetzelfde als wat de "execute" function vraagt, dus dit zal werken maar het verslaat een beetje het doel van de functie in mijn voorbeeld.

Een voorbeeld hoe de DB gebruikt word:
<?php
echo $this->db->prepare("select id where email = ? and password = ?")->execute($email, $password)->fetchField('id');
echo $this->db->prepare("select iets where a = ? and b = ?" and c = ?)->execute($a, $b, $c)->executed();
?>

Execute heeft dus variable argumenten lengte, naartuurlijk kan je met func_get_args() werken, omdaar weer omheen te loopen maar dit is mooier, minder code en mogelijk tot nu :s (zonder problemen)
Je argumenten moeten hetzelfde zijn als in parent class. PDO::execute() gebruikt geen variadic arguments, dus mag die in jouw class dat ook niet doen.
Wouter J op 22/09/2015 18:13:21

Je argumenten moeten hetzelfde zijn als in parent class. PDO::execute() gebruikt geen variadic arguments, dus mag die in jouw class dat ook niet doen.

Dit is dus nieuw in PHP 7?
Nee, PHP gooit altijd al errors als je argumenten niet overeen komen met die in de parent class (behalve bij de constructor).

Reageren