Pimpleの内容物にプロパティとしてアクセス&PhpStormの入力補完を効かせる

Pimpleで配列アクセスするのだるい

すごくだるい。PhpStormの入力補完をアテにしていて、それが効かない構文だからなおのことだるい。

// 入力補完がカケラも効かない
$app['autoloader']->registerNamespace($ns, $pathTo);

enキーボードでチョロまかしてるから幾らかマシですが、jpキーボードだったら更にタイプしづらいんじゃないでしょうか。泣ける。

下のようにやれば部分的には補完効くけどありえない。

/* @var \Symfony\Component\ClassLoader\UniversalClassLoader $autoloader */
$loader = $app['autoloader'];
$app->registerNamespace($in, $pathTo);

鳴かぬなら・・・

改造してしまおう

題材はSilex\Applicationです。

Pimpleの$this->valuesを上書きして、ArrayAccessの実装メソッド類もすべて自前のものとしてオーバーライドします。実装の中身はコピペ。

そして、__getoffsetGetのエイリアスにしてやれば、内容物にプロパティとしてアクセスできます。

// ぬるいほうがいいんだ!!
$app->autoloder->registerNamespace($ns, $pathTo);

コメントには、@propertyを加えてやることで内容物の型も指定できるので、バッチリ入力補完が効くようになります。(PhpStorm 3.03で確認)あとは都度、ServiceProviderも突っ込んでいけばいいですね。

サンプル

<?php

namespace Acme;

/**
 * @property \Symfony\Component\ClassLoader\UniversalClassLoader$autoloader
 * @property \Symfony\Component\Routing\RouteCollection         $routes
 * @property \Silex\ControllerCollection                        $controllers
 * @property \Silex\ExceptionHandler                    $exception_handler
 * @property \Symfony\Component\EventDispatcher\EventDispatcher $dispatcher
 * @property \Silex\RedirectableUrlMatcher                      $url_matcher
 * @property \Silex\ControllerResolver                          $resolver
 * @property \Symfony\Component\HttpKernel\HttpKernel           $kernel
 * @property \Symfony\Component\Routing\RequestContext      $request_context
 */
class Application extends \Silex\Application
{
  /*
   * Override Pimple's ArrayAccess implementation
   */

  protected $values = array();

  public function __get($id)
  {
    return $this[$id];
  }

  public function offsetSet($id, $value)
  {
    $this->values[$id] = $value;
  }

  public function offsetGet($id)
  {
    if (!array_key_exists($id, $this->values)) {
      throw new \InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id));
    }
    return $this->values[$id] instanceof \Closure ? $this->values[$id]($this) : $this->values[$id];
  }

  public function offsetUnset($id)
  {
    unset($this->values[$id]);
  }

  public function offsetExists($id)
  {
    return isset($this->values[$id]);
  }
}
?>

色々アレ

彼方からお叱りの声が聞こえてきそうですが、まあ、満足。