awesome PHP之依赖注入器皿pimple

Jun 13, 2016 am 11:55 AM
callable object the this

awesome PHP之依赖注入容器pimple
依赖注入(Dependency Injection)又叫控制反转(Inversion of Control)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,它能消除组件间的直接依赖关系,让组件的开发更独立,使用更灵活,在java框架中应用非常广泛。在php中由于语言特性不能完全照搬java的那一套,但简单的功能还是可以实现的。pimple就是php社区中比较流行的一种ioc容器。

可以用composer添加 require  "pimple/pimple": "1.*"

pimple的优势是简单,就一个文件

<?php /* * This file is part of Pimple. * * Copyright (c) 2009 Fabien Potencier * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is furnished * to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. *//** * Pimple main class. * * @package pimple * @author  Fabien Potencier */class Pimple implements \ArrayAccess{    private $values = array();    private $factories;    private $protected;    private $frozen = array();    private $raw = array();    private $keys = array();    /**     * Instantiate the container.     *     * Objects and parameters can be passed as argument to the constructor.     *     * @param array $values The parameters or objects.     */    public function __construct(array $values = array())    {        $this->factories = new \SplObjectStorage();        $this->protected = new \SplObjectStorage();        foreach ($values as $key => $value) {            $this->offsetSet($key, $value);        }    }    /**     * Sets a parameter or an object.     *     * Objects must be defined as Closures.     *     * Allowing any PHP callable leads to difficult to debug problems     * as function names (strings) are callable (creating a function with     * the same name as an existing parameter would break your container).     *     * @param  string           $id    The unique identifier for the parameter or object     * @param  mixed            $value The value of the parameter or a closure to define an object     * @throws RuntimeException Prevent override of a frozen service     */    public function offsetSet($id, $value)    {        if (isset($this->frozen[$id])) {            throw new \RuntimeException(sprintf('Cannot override frozen service "%s".', $id));        }        $this->values[$id] = $value;        $this->keys[$id] = true;    }    /**     * Gets a parameter or an object.     *     * @param string $id The unique identifier for the parameter or object     *     * @return mixed The value of the parameter or an object     *     * @throws InvalidArgumentException if the identifier is not defined     */    public function offsetGet($id)    {        if (!isset($this->keys[$id])) {            throw new \InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id));        }        if (            isset($this->raw[$id])            || !is_object($this->values[$id])            || isset($this->protected[$this->values[$id]])            || !method_exists($this->values[$id], '__invoke')        ) {            return $this->values[$id];        }        if (isset($this->factories[$this->values[$id]])) {            return $this->values[$id]($this);        }        $this->frozen[$id] = true;        $this->raw[$id] = $this->values[$id];        return $this->values[$id] = $this->values[$id]($this);    }    /**     * Checks if a parameter or an object is set.     *     * @param string $id The unique identifier for the parameter or object     *     * @return Boolean     */    public function offsetExists($id)    {        return isset($this->keys[$id]);    }    /**     * Unsets a parameter or an object.     *     * @param string $id The unique identifier for the parameter or object     */    public function offsetUnset($id)    {        if (isset($this->keys[$id])) {            if (is_object($this->values[$id])) {                unset($this->factories[$this->values[$id]], $this->protected[$this->values[$id]]);            }            unset($this->values[$id], $this->frozen[$id], $this->raw[$id], $this->keys[$id]);        }    }    /**     * Marks a callable as being a factory service.     *     * @param callable $callable A service definition to be used as a factory     *     * @return callable The passed callable     *     * @throws InvalidArgumentException Service definition has to be a closure of an invokable object     */    public function factory($callable)    {        if (!is_object($callable) || !method_exists($callable, '__invoke')) {            throw new \InvalidArgumentException('Service definition is not a Closure or invokable object.');        }        $this->factories->attach($callable);        return $callable;    }    /**     * Protects a callable from being interpreted as a service.     *     * This is useful when you want to store a callable as a parameter.     *     * @param callable $callable A callable to protect from being evaluated     *     * @return callable The passed callable     *     * @throws InvalidArgumentException Service definition has to be a closure of an invokable object     */    public function protect($callable)    {        if (!is_object($callable) || !method_exists($callable, '__invoke')) {            throw new \InvalidArgumentException('Callable is not a Closure or invokable object.');        }        $this->protected->attach($callable);        return $callable;    }    /**     * Gets a parameter or the closure defining an object.     *     * @param string $id The unique identifier for the parameter or object     *     * @return mixed The value of the parameter or the closure defining an object     *     * @throws InvalidArgumentException if the identifier is not defined     */    public function raw($id)    {        if (!isset($this->keys[$id])) {            throw new \InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id));        }        if (isset($this->raw[$id])) {            return $this->raw[$id];        }        return $this->values[$id];    }    /**     * Extends an object definition.     *     * Useful when you want to extend an existing object definition,     * without necessarily loading that object.     *     * @param string   $id       The unique identifier for the object     * @param callable $callable A service definition to extend the original     *     * @return callable The wrapped callable     *     * @throws InvalidArgumentException if the identifier is not defined or not a service definition     */    public function extend($id, $callable)    {        if (!isset($this->keys[$id])) {            throw new \InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id));        }        if (!is_object($this->values[$id]) || !method_exists($this->values[$id], '__invoke')) {            throw new \InvalidArgumentException(sprintf('Identifier "%s" does not contain an object definition.', $id));        }        if (!is_object($callable) || !method_exists($callable, '__invoke')) {            throw new \InvalidArgumentException('Extension service definition is not a Closure or invokable object.');        }        $factory = $this->values[$id];        $extended = function ($c) use ($callable, $factory) {            return $callable($factory($c), $c);        };        if (isset($this->factories[$factory])) {            $this->factories->detach($factory);            $this->factories->attach($extended);        }        return $this[$id] = $extended;    }    /**     * Returns all defined value names.     *     * @return array An array of value names     */    public function keys()    {        return array_keys($this->values);    }}
ログイン後にコピー

pimple类就继承一个php数组对象接口,在程序整个生命周期中,各种属性、方法、对象、闭包都可以注册其中,得易于php的数组的hashtable实现,容器本身的查询效率不算是太低。类似zf1中的Zend_Register或者Yii的委托代理形式,总体来说还是pimple直观些。

pimple只是实现了一个容器的概念,关于依赖注入自动创建关联对象的功能可以参照Laravel4和z2中的实现。一个例子代码:

require __DIR__ . '/vendor/autoload.php';  // define some services$container['session_storage'] = function ($c) {    return new $c['session_storage_class']($c['cookie_name']);};$container['session'] = function ($c) {    return new Session($c['session_storage']);};// get the session object$session = $container['session'];$container['session'] = $container->factory(function ($c) {    return new Session($c['session_storage']);});
ログイン後にコピー


このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

2か月後、人型ロボットWalker Sが服をたたむことができるようになった 2か月後、人型ロボットWalker Sが服をたたむことができるようになった Apr 03, 2024 am 08:01 AM

Machine Power Report 編集者: Wu Xin 国内版の人型ロボット + 大型模型チームは、衣服を折りたたむなどの複雑で柔軟な素材の操作タスクを初めて完了しました。 OpenAIのマルチモーダル大規模モデルを統合したFigure01の公開により、国内同業者の関連動向が注目を集めている。つい昨日、中国の「ヒューマノイドロボットのナンバーワン株」であるUBTECHは、Baidu Wenxinの大型モデルと深く統合されたヒューマノイドロボットWalkerSの最初のデモを公開し、いくつかの興味深い新機能を示した。 Baidu Wenxin の大規模モデル機能の恩恵を受けた WalkerS は次のようになります。 Figure01 と同様に、WalkerS は動き回るのではなく、机の後ろに立って一連のタスクを完了します。人間の命令に従って服をたたむことができる

Java での Synchronized の原理と使用シナリオ、および Callable インターフェイスの使用法と差異分析 Java での Synchronized の原理と使用シナリオ、および Callable インターフェイスの使用法と差異分析 Apr 21, 2023 am 08:04 AM

1. 基本機能 1. 楽観的ロックで開始し、ロック競合が多発する場合は悲観的ロックに変換する 2. 軽量なロック実装で開始し、長時間ロックを保持するとロックを解除する3. 軽量ロックを実装するときに最もよく使用されるスピン ロック戦略 4. 不公平なロックである 5. リエントラント ロックである 6. 読み取り/書き込みロックではない 2. JVMロック プロセスを同期します。 ロックは、ロックなし、バイアスされたロック、軽量ロック、および重量ロックの状態に分類されます。状況に応じて順次バージョンアップしていきます。偏ったロックは男主人公を鍵、女主人公をスレとするもので、このスレッドだけがこのロックを使用すれば、たとえ結婚証明書を取得しなくても男主人公と女主人公は永遠に幸せに暮らせる(高額回避) -コストオペレーション)しかし、女性のサポート役が登場します

Javaオブジェクトクラスのメソッドの使い方 Javaオブジェクトクラスのメソッドの使い方 Apr 18, 2023 pm 06:13 PM

1. オブジェクト クラスの概要 オブジェクトは、Java によってデフォルトで提供されるクラスです。 Object クラスを除いて、Java のすべてのクラスには継承関係があります。デフォルトでは、Object 親クラスを継承します。つまり、Object のリファレンスを使用して、すべてのクラスのオブジェクトを受け取ることができます。例: Object を使用して、すべてのクラスのオブジェクトを受信します。 classperson{}classStudent{}publicclassTest{publicstaticvoidmain(String[]args){function(newperson());function(newStudent());}public

Java は、オブジェクト クラスの getClass() 関数を使用して、オブジェクトのランタイム クラスを取得します。 Java は、オブジェクト クラスの getClass() 関数を使用して、オブジェクトのランタイム クラスを取得します。 Jul 24, 2023 am 11:37 AM

Java では、Object クラスの getClass() 関数を使用して、オブジェクトのランタイム クラスを取得します。Java では、各オブジェクトには、オブジェクトのプロパティとメソッドを定義するクラスがあります。 getClass() 関数を使用して、オブジェクトのランタイム クラスを取得できます。 getClass() 関数は Object クラスのメンバー関数であるため、すべての Java オブジェクトがこの関数を呼び出すことができます。この記事では、getClass() 関数の使用方法といくつかのコード例を紹介します。取得を使用する

Vue2 がこれを通じてさまざまなオプションのプロパティにアクセスできる理由について話しましょう Vue2 がこれを通じてさまざまなオプションのプロパティにアクセスできる理由について話しましょう Dec 08, 2022 pm 08:22 PM

この記事は、vue ソース コードを解釈するのに役立ち、これを使用して Vue2 のさまざまなオプションのプロパティにアクセスできる理由を紹介します。

Javaオブジェクトをバイトに変換する方法、およびバイトをオブジェクトに変換する方法は何ですか? Javaオブジェクトをバイトに変換する方法、およびバイトをオブジェクトに変換する方法は何ですか? Apr 20, 2023 am 11:37 AM

オブジェクトからバイトへ、そしてバイトからオブジェクトへ 今日は、オブジェクトからバイトに変換する方法、およびバイトからオブジェクトに変換する方法を理解します。まず、クラス Student を定義します。 packagecom.byteToObject;importjava.io.Serializable;publicclassstudentimplementsSerializable{privateintsid;privateStringname;publicintgetSid(){returnsid;}publicvoidsetSid(in)

この点を理解してフロントエンド担当者の7割をキャッチアップした記事 この点を理解してフロントエンド担当者の7割をキャッチアップした記事 Sep 06, 2022 pm 05:03 PM

同僚は、これによって指摘されたバグのために立ち往生しました。Vue2 のこの指摘の問題により、アロー関数が使用され、その結果、対応する props を取得できなくなりました。私がそれを彼に紹介したとき、彼はそれを知りませんでした。その後、私はわざとフロントエンド コミュニケーション グループに目を向けました。これまでのところ、フロントエンド プログラマーの少なくとも 70% はまだそれを理解していません。今日私はそれを共有しますyou this link. もしすべてが間違っている場合 まだ学習していない場合は、大きな口を与えてください。

Javaの基本データ型とオブジェクトの関係は何ですか Javaの基本データ型とオブジェクトの関係は何ですか May 01, 2023 pm 04:04 PM

基本データ型と Object の関係 Object がすべての型の基本クラスであるということは誰もが聞いたことがあると思いますが、Java の基本データ型は Object とは何の関係もないため、この文は実際には正しくありません。たとえば、swap メソッドを呼び出す場合、Object は実際には基本データ型とは何の関係もないため、int 型を swap(Objectobj) メソッドに直接渡すことはできません。このとき、a は型が一致しないことがわかります。自動的にラップされます. Integer 型になっています. この時点で Object に接続でき、swap メソッドを正常に呼び出すことができます. Object、基本データ型のラッパー クラス

See all articles