Jump to content

When to use returning by reference?


NotionCommotion

Recommended Posts

Per http://php.net/manual/en/language.references.return.php

Returning by reference is useful when you want to use a function to find to which variable a reference should be bound. Do not use return-by-reference to increase performance. The engine will automatically optimize this on its own. Only return references when you have a valid technical reason to do so. To return references, use this syntax:

 

 

 

The following four examples are provided in the documentation.  Example 2 makes perfect sense, but not really examples 1, 3, or 4.  Can anyone shed some light on how the returned reference would be used?

<?php
//Example 1. http://php.net/manual/en/language.references.pass.php
function foo(&$var)
{
    $var++;
}
function &bar()
{
    $a = 5;
    return $a;
}
foo(bar());


//Example 2. http://php.net/manual/en/language.references.return.php
class foo {
    public $value = 42;


    public function &getValue() {
        return $this->value;
    }
}
$obj = new foo;
$myValue = &$obj->getValue(); // $myValue is a reference to $obj->value, which is 42.
$obj->value = 2;
echo $myValue;                // prints the new value of $obj->value, i.e. 2.


//Example 3. http://php.net/manual/en/language.references.return.php
function &collector1() {
  static $collection1 = array();
  return $collection1;
}
$collection1 = &collector1();
$collection1[] = 'foo';


//Example 4. http://php.net/manual/en/language.references.return.php
function &collector2() {
  static $collection2 = array();
  return $collection2;
}
array_push(collector2(), 'foo');

 

Link to comment
Share on other sites

Do you have specific questions or just want to understand what they're doing?

 

#1 uses return-by-reference and pass-by-reference. It's just a trivial example to show both happening at once. One without the other and the code wouldn't work.

 

#3 demonstrates a function using a static variable (so that all calls to it use the same variable) and return-by-reference (so that callers can modify the variable directly). Without the reference collector1() would have to provide some way to modify the value, but since it's a local static variable that means fun stuff like

function collector1($key = null, $value = null, $addnull = false) {
	static $collection1 = array();
	if ($value !== null || $addnull) {
		if ($key === null) {
			$collection1[] = $value;
		} else {
			$collection1[$key] = $value;
		}
	}
}
If you can't trust callers to manipulate $collection1 properly then you're forced into something like the above, but if you do can then it's much easier to use a reference.

 

#4 is the same thing but without the temporary $collection1 variable.

Link to comment
Share on other sites

As a somewhat practical example of when you might want to return a reference, say for example you have a largish array tree (maybe something you json_decoded) and want to access it using a dot-separated path. You might have a function that can turn that path into a reference to that part of the tree which you could then manipulate if you wanted to.

 

For example

$config = [
    'doctrine' => [
        'dbal' => [
            'default_connection' => 'default'
            , 'connections' => [
                'default' => [
                    'driver' => "%database_driver%"
                    , 'host' => "%database_host%"
                    , 'port' => "%database_port%"
                    , 'dbname' => "%database_name%"
                    , 'user' => "%database_user%"
                    , 'password' => "%database_password%"
                    , 'charset' => 'UTF8'
                ]
                , 'special' => [
                    'driver' => "%database_driver%"
                    , 'host' => "%database_host%"
                    , 'port' => "%database_port%"
                    , 'dbname' => "%database_name_special%"
                    , 'user' => "%database_user_special%"
                    , 'password' => "%database_password_special%"
                    , 'charset' => 'UTF8'
                ]
            ]
        ]                
        , 'orm' => [
            'default_entity_manager' => 'default'
            , 'auto_generate_proxy_classes' => "%kernel.debug%"
            , 'entity_managers' => [
                'default' => [
                    'connection' => 'default'
                    , 'naming_strategy' => 'doctrine.orm.naming_strategy.underscore'
                    , 'mappings' => [
                        'AppBundle' => [
                            'type' => 'yml'
                            , 'dir' => 'Resources/config/doctrine'
                            , 'alias' => 'AppBundle'
                        ]
                    ]
                ]
            ]
        ]
    ]
    , 'swiftmailer' => [
        'transport' => "%mailer_transport%"
        , 'host' => "%mailer_host%"
        , 'username' => "%mailer_user%"
        , 'password' => "%mailer_password%"
        , 'spool' => ['type' => 'memory' ]
    ]
];


var_dump($config['doctrine']['dbal']['default_connection']);
$connection = &getKey($config, 'doctrine.dbal.default_connection');
$connection = 'special';
var_dump($config['doctrine']['dbal']['default_connection']);

function &getKey(&$config, $path){
    if (strpos($path, '.') !== false){
        list($key, $path) = explode('.', $path, 2);
        return getKey($config[$key], $path);
    } else {
        return $config[$path];
    }
}

  • Like 1
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.