awesome PHP之依赖注入器皿pimple
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']);});

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

機器之能報道編輯:吳昕國內版的人形機器人+大模型組隊,首次完成疊衣服這類複雜柔性材料的操作任務。隨著融合了OpenAI多模態大模型的Figure01揭開神秘面紗,國內同行的相關進展一直備受關注。就在昨天,國內"人形機器人第一股"優必選發布了人形機器人WalkerS深入融合百度文心大模型後的首個Demo,展示了一些有趣的新功能。現在,得到百度文心大模型能力加持的WalkerS是這個樣子的。和Figure01一樣,WalkerS沒有走動,而是站在桌子後面完成一系列任務。它可以聽從人類的命令,折疊衣物

一、基本特性1.一開始是樂觀鎖,如果鎖衝突頻繁,就轉換為悲觀鎖.2.開始是輕量級鎖實現,如果鎖被持有的時間較長,就轉換成重量級鎖. 3.實現輕量級鎖的時候大概率用到的自旋鎖策略4.是一種不公平鎖5.是一種可重入鎖6.不是讀寫鎖二、加鎖工作過程JVM將synchronized鎖分為無鎖、偏向鎖、輕量級鎖、重量級鎖狀態。會根據情況,進行依序升級。偏向鎖假設男主角是一個鎖,女主角是一個線程.如果只有這一個線程來使用這個鎖,那麼男主女主即使不領證結婚(避免了高成本操作),也可以一直幸福的生活下去.但是女配出現

Java使用Object類別的getClass()函數取得物件的執行時間類別在Java中,每個物件都有一個類,這個類別定義了物件的屬性和方法。我們可以使用getClass()函數來取得物件的運行時類別。 getClass()函數是Object類別的成員函數,所以所有的Java物件都可以呼叫該函數。本文將介紹getClass()函數的使用方法以及給一些程式碼範例。使用get

1.Object類別介紹Object是Java預設提供的一個類別。 Java裡面除了Object類,所有的類別都是存在繼承關係的。預設會繼承Object父類別。即所有類別的物件都可以使用Object的參考來接收。範例:使用Object接收所有類別的物件classPerson{}classStudent{}publicclassTest{publicstaticvoidmain(String[]args){function(newPerson());function(newStudent());}public

這篇文章帶大家解讀vue原始碼,來介紹一下Vue2中為什麼可以使用 this 存取各種選項中的屬性,希望對大家有幫助!

Object轉byte與byte轉Object今天實作如何從Object去轉為byte和如何從byte轉為Object。首先,定義一個類別student:packagecom.byteToObject;importjava.io.Serializable;publicclassstudentimplementsSerializable{privateintsid;privateStringname;publicintgetSid(){returnsid;}publicvoidsetSid(in

同事因為this指向的問題卡住的bug,vue2的this指向問題,使用了箭頭函數,導致拿不到對應的props。當我跟他介紹的時候他竟然不知道,隨後也刻意的看了一下前端交流群,至今最起碼還有70%以上的前端程式設計師搞不明白,今天給大家分享一下this指向,如果啥都沒學會,請給我一個大嘴巴子。

基本資料型別與Object的關係我知道大家是不是都聽說過Object是所有類型的基類,但是這句話其實並不是正確的,因為java中基本資料型別跟Object是沒有任何關係的.這裡舉一個例子這裡在進行呼叫swap方法時,是不能直接將int型別傳給swap(Objectobj)方法的,因為Object其實跟基本資料型別沒有一點關係,這時候a就發現我們型別不匹配,所以就自動包裝成了Integer型別了,這個時候就能跟Object產生聯繫了,才能成功呼叫swap方法了.Object、基本資料型別的包裝類
