BeginnerEngineerBlog
中の人
中の人

【php ArrayAccess】オブジェクトを配列みたいに扱いたい

公開: 2023-01-01 19:54
更新: 2023-04-05 23:07
591
php ArrayAccess 配列 EccubeConfig
eccube4でeccubeConfigというオブジェクトを配列のように利用していてどういうことなんだろうと思って調べてみました

あけましておめでとうございます!
今年もBeginnerEngineerBlogをよろしくお願いします!🙇‍♂️
2023年お互いがんばっていきましょう!

中の人です!
eccube4系を触った方ならわかると思いますが

<?php

namespace Eccube\Form\Type\Admin;

// ..省略
use Eccube\Common\EccubeConfig;
// ..省略

class OrderMailType extends AbstractType
{
    /**
     * @var EccubeConfig
     */
    protected $eccubeConfig;

    /**
     * MailType constructor.
     *
     * @param EccubeConfig $eccubeConfig
     */
    public function __construct(
        EccubeConfig $eccubeConfig
    ) {
        $this->eccubeConfig = $eccubeConfig;
    }

    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('template', MailTemplateType::class, [
                'required' => false,
                'mapped' => false,
                'query_builder' => function (EntityRepository $er) {
                    return $er->createQueryBuilder('mt')
                        ->andWhere('mt.id = :id')
                                                     // 👇こいつ
                        ->setParameter('id', $this->eccubeConfig['eccube_order_mail_template_id'])
                        ->orderBy('mt.id', 'ASC');
                },
            ])
// ..省略

->setParameter('id', $this->eccubeConfig['eccube_order_mail_template_id'])

こんな処理を見たことあると思いますが、なんでオブジェクトに配列のkeyを指定してるんじゃいと思いますよね?
私は今までろくに調べないで、なんかeccubeが独自に関数作って利用してるんかなーと思ってこういうもんだということで使ってたのですが、最近調べてみたらへーと感じたので紹介したいと思います。


ArrayAccessインターフェース


ArrayAccessインターフェースとはphpで用意されているインターフェースで、EccubeConfigにちゃんと実装されてました。

<?php

/*
 * This file is part of EC-CUBE
 *
 * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
 *
 * http://www.ec-cube.co.jp/
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Eccube\Common;

use Symfony\Component\DependencyInjection\ContainerInterface;

                              // 👇これ
class EccubeConfig implements \ArrayAccess
{
    /**
     * @var ContainerInterface
     */
    protected $container;

    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    /**
     * @param $key
     *
     * @return mixed
     */
    public function get($key)
    {
        return $this->container->getParameter($key);
    }

    /**
     * @param $key
     *
     * @return bool
     */
    public function has($key)
    {
        return $this->container->hasParameter($key);
    }

    /**
     * @param $key
     * @param $value
     */
    public function set($key, $value)
    {
        $this->container->setParameter($key, $value);
    }

    /**
     * @param mixed $offset
     *
     * @return bool
     */
    #[\ReturnTypeWillChange]
    public function offsetExists($offset)
    {
        return $this->has($offset);
    }

    /**
     * @param mixed $offset
     *
     * @return mixed
     */
    #[\ReturnTypeWillChange]
    public function offsetGet($offset)
    {
        return $this->get($offset);
    }

    /**
     * @param mixed $offset
     * @param mixed $value
     */
    #[\ReturnTypeWillChange]
    public function offsetSet($offset, $value)
    {
        $this->set($offset, $value);
    }

    /**
     * @param mixed $offset
     *
     * @throws \Exception
     */
    #[\ReturnTypeWillChange]
    public function offsetUnset($offset)
    {
        throw new \Exception();
    }
}


ということでこのインターフェースを実装したクラスを作成するとオブジェクトを配列のように扱えます。
ドキュメントから↓(__constructの部分だけ使いやすいように変えてます)
📁 Obj.php
<?php

class Obj implements ArrayAccess {

    private $container = array();

    public function __construct(
        array $array
    ) {
        $this->container = $array;
    }

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

📁 test.php
<?php

require_once ('./Obj.php');

$array = [
    "one"   => 1,
    "two"   => 2,
    "three" => 3,
];
$obj = new Obj($array);

var_dump($obj['test']);

$obj['test'] = 'osu';

var_dump($obj['test']);
var_dump($obj['one']);


これの実行結果は以下になります。

NULL
string(3) "osu"
int(1)

になります。

こちらにわかりやすく解説してくれてますので一読してみてください。

コアは多分ブラックボックス化してる感じがしたので深く追ってません。
というか追えませんでした。


最後に


まぁこんな感じでオブジェクトを配列として使いたい場合は使ってみるのも乙な感じがします。
ということでなんか気が向いたときに実装してみるといいかもしれません。

ということで、おつ!
0
0
0
0
通信エラーが発生しました。
【広告】
似たような記事