2

I am trying to grasp an OOP concept brought into PHP 7+ for Conflict Resolution. I also want to make a dynamic call to save() in my design, which will take in a argument by reference.

To test the concept before I created this addition to my framework, I wanted to try the basics of simply outputting the zval of a variable.

My current trait looks like this:

trait Singleton {
    # Holds Parent Instance
    private static  $_instance;
    # Holds Current zval
    private         $_arg;

    # No Direct Need For This Other Than Stopping Call To new Class
    private function __construct() {}

    # Singleton Design
    public static function getInstance() {
        return self::$_instance ?? (self::$_instance = new self());
    }

    # Store a reference of the variable to share the zval
    # If I set $row before I execute this method, and echo $arg
    # It holds the correct value, _arg is not saving this same value?
    public function bindArg(&$arg) { $this->_arg = $arg; }

    # Output the value of the stored reference if exists
    public function helloWorld() { echo $this->_arg ?? 'Did not exist.'; }
}

I then created a class which utilises the Singleton trait.

final class Test {
    use \Singleton { helloWorld as public peekabo; }
}

I passed in the variable I wanted to reference like so, since the method expects a reference of the variable - it does not need to be set yet.

Test::getInstance()->bindArg($row);

I now want to mimic the concept of looping through rows from a database result, the concept is to allow a save() method to be added to my design, but getting the basic concept working comes first.

foreach(['Hello', ',', ' World'] as $row)
    Test::getInstance()->peekabo();

The issue is, the output looks like this:

Did not exist.Did not exist.Did not exist.

My expected output would look like:

Hello, World

How can I store the zval inside of my class for later usage within a separate method?


Demo for future viewers of this now working thanks to the answers

Demo of this working for a database concept like I explained in the question here:

"I now want to mimic the concept of looping through rows from a database result, the concept is to allow a save() method to be added to my design"

Jaquarh
  • 6,493
  • 7
  • 34
  • 86
  • looks like you are not calling bindArg in the foreach loop. so $_arg is not being set. – RyDog Jan 10 '19 at 22:05
  • `bindArg` should only store the variable by reference, so only one call needs to be made. As the value of `$row` changes, `peekabo()` should output the value of the changed value of `$row` since `$this->_arg`should hold the same zval @RyDog – Jaquarh Jan 10 '19 at 22:08
  • [`\PDOStatement::bindParam`](http://php.net/manual/en/pdostatement.bindparam.php) is a perfect example of what I am trying to achieve. Since [`PDOStatement::execute`](http://php.net/manual/en/pdostatement.execute.php) holds the zval for the values (hence why `bindParam()` can be called before the variable is even set) as long as it is set before a call to `execute()` is made. I hope that makes a bit more sense @RyDog – Jaquarh Jan 10 '19 at 22:16

1 Answers1

3

Use public function bindArg(&$arg) { $this->_arg = &$arg; } It works with PHP 7.3

Lukas
  • 201
  • 1
  • 4
  • Jesus Christ, I assumed that because `&$arg` was being passed in, `$arg` would hold the reference to the variable, not the value. Passing `$arg` by reference to `$this->_arg` now works. Here is a [demo](https://3v4l.org/EWJs2) for future viewers. Thank you a lot! – Jaquarh Jan 10 '19 at 22:24
  • If anyone is interested in this approach which I explained in question with using pass-by-reference with MVC. I have implemented this test as a DB model. Here is an [example](https://3v4l.org/bb724) of how it could look. You just need to set up the connections and you're good to use it how you like. You can dynamically save your data, delete your data or whatever you like. – Jaquarh Jan 10 '19 at 23:07