tmkiernan
tmkiernan

Reputation: 372

How does Laravel use the app object like its an array?

I am setting up an application in PHP, trying to follow some of the conventions laid down in Laravel, I can see there are lots of references to $this->app["some_var"];

But in my app it throws an error saying "Cannot use object as an array".

I am aware that Laravel uses magic methods such as __get() and __set() which I have included, however I still get the same results.

The magic getter and setter code I have used in the parent class of my App object

  /**
  * Dynamically access container services.
  *
  * @param  string  $key
  * @return mixed
  */
  public function __get($key)
  {
    return $this[$key];
  }

  /**
   * Dynamically set container services.
   *
   * @param  string  $key
   * @param  mixed   $value
   * @return void
   */
  public function __set($key, $value)
  {
    $this[$key] = $value;
  }

Expected result is for it to access any property that is innaccessable on the object?

Currently throws a Fatal error: Uncaught Error: Cannot use object Application as type of array.

Upvotes: 5

Views: 1268

Answers (3)

Sugan Krishna
Sugan Krishna

Reputation: 413

Array and Object are two different data types in PHP. For accessing array variables, we need to use square brackets [ ]. For example,

$a = array('one','two','three');
$a[] = "four";
echo $a[3]; //Output: four.

But, for accessing object variables

$a = new {className}();
$a->key = 'value'; //Using magic method __get()
echo $a->key; //Output: value

In terms of class, $this refers to object that specific class. So, you can't assign variable using [ ] square brackets. You need to use -> arrow for that purpose.

Inside class, you need to rewrite your function as below

public function __get($key) {
 return $this->$key ?: false;
}

public function __set($key,$value) {
 $this->$key = $value;
}

Or else, you can create a new array variable inside class as below

class className {
 public $a = array();
 public function __get($key) {
   return $this->a[$key] ?: false;
 }
 public function __set($key,$value) {
   return $this->a[$key] = $value;
 }
}

Upvotes: 0

Troyer
Troyer

Reputation: 7013

The class Application from Laravel kernel extends a Container class that implements ArrayAccess.

There are multiple ways to build an ArrayAccess interface, Laravel uses a complex one because it should satisfy more requisites than a defualt one, but in a short answer you need to provide an implementation for the offsetExists(), offsetGet(), offsetSet(), and offsetUnset() methods and then you can use ArrayAccess syntax.

You can see an extended usage of ArrayAccess in your Container class, by default on the vendor, following next path: Illuminate\Container\Container and there is the code implementing the methods:

/**
 * Determine if a given offset exists.
 *
 * @param  string  $key
 * @return bool
 */
public function offsetExists($key)
{
    return isset($this->bindings[$key]);
}

/**
 * Get the value at a given offset.
 *
 * @param  string  $key
 * @return mixed
 */
public function offsetGet($key)
{
    return $this->make($key);
}

/**
 * Set the value at a given offset.
 *
 * @param  string  $key
 * @param  mixed   $value
 * @return void
 */
public function offsetSet($key, $value)
{
    // If the value is not a Closure, we will make it one. This simply gives
    // more "drop-in" replacement functionality for the Pimple which this
    // container's simplest functions are base modeled and built after.
    if (! $value instanceof Closure) {
        $value = function () use ($value) {
            return $value;
        };
    }

    $this->bind($key, $value);
}

/**
 * Unset the value at a given offset.
 *
 * @param  string  $key
 * @return void
 */
public function offsetUnset($key)
{
    unset($this->bindings[$key], $this->instances[$key], $this->resolved[$key]);
}

Simpliest way to understand ArrayAccess is like Somesh Mukherjee answer explained.

Upvotes: 1

SoWhat
SoWhat

Reputation: 5622

You need to implement ArrayAccess See below code from https://www.php.net/manual/en/class.arrayaccess.php The following code stores the array values in $container array and proxies $obj['key'] to this array object

<?php
class obj implements ArrayAccess {
    private $container = array();

    public function __construct() {
        $this->container = array(
            "one"   => 1,
            "two"   => 2,
            "three" => 3,
        );
    }

    public function offsetSet($offset, $value) {
        if (is_null($offset)) {
            $this->container[] = $value;
        } else {
            $this->container[$offset] = $value;
        }
    }

    public function offsetExists($offset) {
        return isset($this->container[$offset]);
    }

    public function offsetUnset($offset) {
        unset($this->container[$offset]);
    }

    public function offsetGet($offset) {
        return isset($this->container[$offset]) ? $this->container[$offset] : null;
    }
}

$obj = new obj;

var_dump(isset($obj["two"]));
var_dump($obj["two"]);
unset($obj["two"]);
var_dump(isset($obj["two"]));
$obj["two"] = "A value";
var_dump($obj["two"]);
$obj[] = 'Append 1';
$obj[] = 'Append 2';
$obj[] = 'Append 3';
print_r($obj);
?>

Upvotes: 1

Related Questions