0

The following results in error PHP Fatal error: Constant expression contains invalid operations. I can obviously create a new method updateArrayOfNodes(), however, I don't care to do so for the marginal performance increase. I think the performance to repeatably re-create the prepared statement is a bigger deal. How can I reuse the prepared statement within a method?

class mapper
{
    public function update(Entities\Node $node){
        static $stmt=$this->pdo->prepare('UPDATE series SET name=:name, position=:position WHERE id=:id');
        return $stmt->execute(['name'=>$node->name, 'position'=>$node->position, 'id'=>$node->id]);
    }    
}

$mapper=new mapper();
foreach($arr as $node) $mapper->update($node);
user1032531
  • 24,767
  • 68
  • 217
  • 387
  • Possible duplicate of [PHP Error : Fatal error: Constant expression contains invalid operations](https://stackoverflow.com/questions/40171546/php-error-fatal-error-constant-expression-contains-invalid-operations) – aynber Jun 12 '18 at 20:08
  • @aynber I recognized why I was getting the error. Maybe I should have phrased the question "Making prepared statement persistent within method". – user1032531 Jun 12 '18 at 20:13
  • Gotcha. You really don't need a static variable for this. Since you're instantiating the class and reusing it, create it as a class variable. You can instead assign the prepared statement to the variable within the constructor, rather than checking it each time you call the function. You really only need static variables when you're also calling the function statically. – aynber Jun 12 '18 at 20:23

1 Answers1

2

Why not create a protected property and init it once:

class mapper
{

    protected $stmt;

    public function update(Entities\Node $node){
        if (!$this->stmt) {
            $this->stmt = $this->pdo->prepare('UPDATE series SET name=:name, position=:position WHERE id=:id');
        }
        return $this->stmt->execute(['name'=>$node->name, 'position'=>$node->position, 'id'=>$node->id]);
    }    
}

Or going further - create method like updateBatch() and pass an array there, so instead of:

$mapper=new mapper();
foreach($arr as $node) $mapper->update($node);

use:

$mapper=new mapper();
$mapper->updateBatch($arr);

Usage of static variable should be something like:

public function update(Entities\Node $node){
    static $stmt;
    if (!$stmt) {
        $stmt=$this->pdo->prepare('UPDATE series SET name=:name, position=:position WHERE id=:id');
    }
    return $stmt->execute(['name'=>$node->name, 'position'=>$node->position, 'id'=>$node->id]);
}  
u_mulder
  • 54,101
  • 5
  • 48
  • 64
  • Thanks u_mulder. I know that static variables are usually frowned on, but I thought this might have been an acceptable use. I will likely do exactly as you have shown. – user1032531 Jun 12 '18 at 20:09
  • I see your last example where a static variable is used. Would you recommend not doing so? It doesn't seem to cause any testing problems and it cleans up the namespace a little bit. – user1032531 Jun 12 '18 at 20:14
  • Not sure what to tell about static variables, cause I don't work with them) Maybe it doesn't cause any testing problem, but once some entity accidentally changes value of this variable, all other entities will see that and debugging can be hard. – u_mulder Jun 12 '18 at 20:17