Как Laravel использует объект приложения как массив? - PullRequest
4 голосов
/ 21 мая 2019

Я настраиваю приложение на PHP, пытаюсь следовать некоторым соглашениям, изложенным в Laravel, я вижу, что есть много ссылок на $this->app["some_var"];

Но в моем приложении выдается сообщение об ошибке «Невозможно использовать объект в качестве массива».

Я знаю, что Laravel использует магические методы, такие как __get() и __set() который я включил, однако я все еще получаю те же результаты.

Волшебный код получения и установки, который я использовал в родительском классе моего объекта приложения

  /**
  * 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;
  }

Ожидаемый результат - получить доступ к любому свойству, недоступному для объекта?

В настоящее время выдает Fatal error: Uncaught Error: Cannot use object Application as type of array.

Ответы [ 3 ]

1 голос
/ 21 мая 2019

Класс Application из ядра Laravel расширяет класс Container, который реализует ArrayAccess .

Существует несколько способов создания интерфейса ArrayAccess, Laravel использует сложный, потому что он должен удовлетворять большему количеству реквизитов, чем по умолчанию, но в кратком ответе вам необходимо предоставить реализацию для offsetExists (), offsetGet(), offsetSet () и offsetUnset (), а затем вы можете использовать синтаксис ArrayAccess.

Вы можете увидеть расширенное использование ArrayAccess в вашем классе-контейнере по умолчанию у поставщика по следующему пути: Illuminate\Container\Container и есть код, реализующий методы:

/**
 * 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]);
}

Самый простой способ понять ArrayAccess - это как объяснить ответ Сомеша Мукерджи.

1 голос
/ 21 мая 2019

Вам необходимо реализовать ArrayAccess. См. Ниже код из https://www.php.net/manual/en/class.arrayaccess.php Следующий код сохраняет значения массива в массиве $ container и передает $ obj ['key'] этому объекту массива

<?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);
?>
0 голосов
/ 21 мая 2019

Array и Object - это два разных типа данных в PHP.Для доступа к переменным массива нам нужно использовать квадратные скобки [] .Например,

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

Но для доступа к переменным объекта

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

В терминах класса $ this относится к объекту этого конкретного класса.Таким образом, вы не можете назначить переменную используя [] квадратные скобки.Для этого вам нужно использовать стрелку -> .

Внутри класса вам нужно переписать свою функцию, как показано ниже:

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

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

Или же вы можете создатьновая переменная массива внутри класса, как показано ниже

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