search
HomeBackend DevelopmentPHP TutorialPHP的PSR-0标准利用namespace来做autoloading

介绍PSR-0之前,先来说说命名空间(NameSpace)和Autoloading吧。

NameSpace(命名空间)

namespace是PHP5.3版本加入的新特性,用来解决在编写类库或应用程序时创建可重用的代码如类或函数时碰到的两类问题:

1.用户编写的代码与PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲突。
2.为很长的标识符名称(通常是为了缓解第一类问题而定义的)创建一个别名(或简短)的名称,提高源代码的可读性。

PHP 命名空间中的元素使用了类似文件系统的原理。例如,类名可以通过三种方式引用:
1.非限定名称,或不包含前缀的类名称,例如 $a=new foo(); 或 foo::staticmethod();。如果当前命名空间是 currentnamespace,foo 将被解析为 currentnamespace\foo。如果使用 foo 的代码是全局的,不包含在任何命名空间中的代码,则 foo 会被解析为foo。 警告:如果命名空间中的函数或常量未定义,则该非限定的函数名称或常量名称会被解析为全局函数名称或常量名称。详情参见 使用命名空间:后备全局函数名称/常量名称。
2.限定名称,或包含前缀的名称,例如 $a = new subnamespace\foo(); 或 subnamespace\foo::staticmethod();。如果当前的命名空间是 currentnamespace,则 foo 会被解析为 currentnamespace\subnamespace\foo。如果使用 foo 的代码是全局的,不包含在任何命名空间中的代码,foo 会被解析为subnamespace\foo。
3.完全限定名称,或包含了全局前缀操作符的名称,例如, $a = new \currentnamespace\foo(); 或 \currentnamespace\foo::staticmethod();。在这种情况下,foo 总是被解析为代码中的文字名(literal name)currentnamespace\foo。

另外注意访问任意全局类、函数或常量,都可以使用完全限定名称,例如 \strlen() 或 \Exception 或 \INI_ALL。

<?phpuse My\Full\Classname as Another, My\Full\NSname;$obj = new Another; // 实例化一个 My\Full\Classname 对象$obj = new \Another; // 实例化一个Another对象$obj = new Another\thing; // 实例化一个My\Full\Classname\thing对象$obj = new \Another\thing; // 实例化一个Another\thing对象$a = \strlen('hi'); // 调用全局函数strlen$b = \INI_ALL; // 访问全局常量 INI_ALL$c = new \Exception('error'); // 实例化全局类 Exception?>

以上是namespace的简要介绍,对此不了解的同学还是把细读文档吧。在众多新的PHP项目中,namespace已经被普遍使用了。尤其是伴随Composer的流行,它已经是很有必要去了解的特性了。


Autoloading(自动加载)

很多开发者写面向对象的应用程序时对每个类的定义建立一个 PHP 源文件。一个很大的烦恼是不得不在每个脚本开头写一个长长的包含(require, include)文件列表(每个类一个文件)。

而Autoloading,就是解决这个问题的,通过定义一个/系列autoload函数,它会在试图使用尚未被定义的类时自动调用。通过调用autoload函数,脚本引擎在 PHP 出错失败前有了最后一个机会加载所需的类。这个autoload函数可以是默认的__autoload(),如下:

<?phpfunction __autoload($class_name) {    require_once $class_name . '.php';}$obj  = new MyClass();
也可以采用更灵活的方式,通过spl_autoload_register()来定义我们自己的__autoload()函数:

<?phpfunction my_autoload($class_name) {	require_once $class_name . '.php';}spl_autoload_register("my_autoload");$obj  = new MyClass();
以上代码将my_autoload()函数注册到__autoload栈中,从而取到__autoload()函数(__autoload()函数将不再起作用,但可以显式的将其注册到__autoload栈)。注意到刚才提到了__autoload栈,意味着我们可以注册多个autoload函数,根据注册的顺序依次加载(通过spl_autoload_register的第三个参数可以改变这一顺序)。

在这里我们展示了autoload函数最简单的例子,当然通过一些规则的设置,也可以胜任实际环境中许多复杂的情况。

但是如果我们的项目依赖某些其他的项目,本来大家在各自独立的加载规则下能顺利运行,但融合在一起可能就不妙了。那么能否有一种通用的加载规则来解决这个问题?

PSR-0

PSR是由PHP Framework Interoperability Group(PHP通用性框架小组)发布的一系列标准/规范,目前包括了PSR-0~PSR-4共4个,而PSR-0就是其中的自动加载标准(其后的PSR-4称为改进的自动加载的标准,是PSR-0的补充。PSR-0使用更广泛)。https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md

下面描述了具体互操作性的自动加载所必须的条件:

强制要求

  • 一个完全合格的namespace和class必须符合这样的结构 \\(\)*
  • 每个namespace必须有一个顶层的namespace("Vendor Name"提供者名字)
  • 每个namespace可以有多个子namespace
  • 当从文件系统中加载时,每个namespace的分隔符要转换成 DIRECTORY_SEPARATOR(操作系统路径分隔符)
  • 在CLASS NAME(类名)中,每个下划线(_)符号要转换成DIRECTORY_SEPARATOR。在namespace中,下划线(_)符号是没有(特殊)意义的。
  • 当从文件系统中载入时,合格的namespace和class一定是以 .php 结尾的
  • verdor name,namespaces,class名可以由大小写字母组合而成(大小写敏感的)
  • 除此之外可能还会遵循这个规则:如果文件不存在则返回false。


    例子

  • \Doctrine\Common\IsolatedClassLoader => /path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php
  • \Symfony\Core\Request => /path/to/project/lib/vendor/Symfony/Core/Request.php
  • \Zend\Acl => /path/to/project/lib/vendor/Zend/Acl.php
  • \Zend\Mail\Message => /path/to/project/lib/vendor/Zend/Mail/Message.php
  • NameSpace和Class Name中的下划线

  • \namespace\package\Class_Name => /path/to/project/lib/vendor/namespace/package/Class/Name.php
  • \namespace\package_name\Class_Name => /path/to/project/lib/vendor/namespace/package_name/Class/Name.php
  • 实现的范例

    下面是一个按照如上标准进行自动加载的简单范例:

    <?phpfunction autoload($className){    //这里的$className一般是用namespace的方式来引用的,文章开头已有介绍    //去除$className左边的'\' 这是PHP5.3的一个bug,详见https://bugs.php.net/50731    $className = ltrim($className, '\\');    $fileName  = '';    $namespace = '';    //找到最后一个namespace分隔符的位置    if ($lastNsPos = strrpos($className, '\\')) {        $namespace = substr($className, 0, $lastNsPos);        $className = substr($className, $lastNsPos + 1);        $fileName  = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;    }    $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';    require $fileName;}

    SplClassLoader 的实现

    下面有一个SplClassLoader 的实现范例,如果你遵循了如上的标准,可以用它来进行自动加载。这也是目前PHP5.3推荐的类加载标准。 http://gist.github.com/221634

    <?php /* * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * This software consists of voluntary contributions made by many individuals * and is licensed under the MIT license. For more information, see * <http://www.doctrine-project.org>. */ /** * SplClassLoader implementation that implements the technical interoperability * standards for PHP 5.3 namespaces and class names. * * http://groups.google.com/group/php-standards/web/psr-0-final-proposal?pli=1 * *     // Example which loads classes for the Doctrine Common package in the *     // Doctrine\Common namespace. *     $classLoader = new SplClassLoader('Doctrine\Common', '/path/to/doctrine'); *     $classLoader->register(); * * @license http://www.opensource.org/licenses/mit-license.html  MIT License * @author Jonathan H. Wage <jonwage> * @author Roman S. Borschel <roman> * @author Matthew Weier O'Phinney <matthew> * @author Kris Wallsmith <kris.wallsmith> * @author Fabien Potencier <fabien.potencier> */class SplClassLoader{    private $_fileExtension = '.php';    private $_namespace;    private $_includePath;    private $_namespaceSeparator = '\\';     /**     * Creates a new <tt>SplClassLoader</tt> that loads classes of the     * specified namespace.     *      * @param string $ns The namespace to use.     */    public function __construct($ns = null, $includePath = null)    {        $this->_namespace = $ns;        $this->_includePath = $includePath;    }     /**     * Sets the namespace separator used by classes in the namespace of this class loader.     *      * @param string $sep The separator to use.     */    public function setNamespaceSeparator($sep)    {        $this->_namespaceSeparator = $sep;    }     /**     * Gets the namespace seperator used by classes in the namespace of this class loader.     *     * @return void     */    public function getNamespaceSeparator()    {        return $this->_namespaceSeparator;    }     /**     * Sets the base include path for all class files in the namespace of this class loader.     *      * @param string $includePath     */    public function setIncludePath($includePath)    {        $this->_includePath = $includePath;    }     /**     * Gets the base include path for all class files in the namespace of this class loader.     *     * @return string $includePath     */    public function getIncludePath()    {        return $this->_includePath;    }     /**     * Sets the file extension of class files in the namespace of this class loader.     *      * @param string $fileExtension     */    public function setFileExtension($fileExtension)    {        $this->_fileExtension = $fileExtension;    }     /**     * Gets the file extension of class files in the namespace of this class loader.     *     * @return string $fileExtension     */    public function getFileExtension()    {        return $this->_fileExtension;    }     /**     * Installs this class loader on the SPL autoload stack.     */    public function register()    {        spl_autoload_register(array($this, 'loadClass'));    }     /**     * Uninstalls this class loader from the SPL autoloader stack.     */    public function unregister()    {        spl_autoload_unregister(array($this, 'loadClass'));    }     /**     * Loads the given class or interface.     *     * @param string $className The name of the class to load.     * @return void     */    public function loadClass($className)    {        if (null === $this->_namespace || $this->_namespace.$this->_namespaceSeparator === substr($className, 0, strlen($this->_namespace.$this->_namespaceSeparator))) {            $fileName = '';            $namespace = '';            if (false !== ($lastNsPos = strripos($className, $this->_namespaceSeparator))) {                $namespace = substr($className, 0, $lastNsPos);                $className = substr($className, $lastNsPos + 1);                $fileName = str_replace($this->_namespaceSeparator, DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;            }            $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . $this->_fileExtension;             require ($this->_includePath !== null ? $this->_includePath . DIRECTORY_SEPARATOR : '') . $fileName;        }    }}</fabien.potencier></kris.wallsmith></matthew></roman></jonwage>

    完。


    Statement
    The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
    The Continued Use of PHP: Reasons for Its EnduranceThe Continued Use of PHP: Reasons for Its EnduranceApr 19, 2025 am 12:23 AM

    What’s still popular is the ease of use, flexibility and a strong ecosystem. 1) Ease of use and simple syntax make it the first choice for beginners. 2) Closely integrated with web development, excellent interaction with HTTP requests and database. 3) The huge ecosystem provides a wealth of tools and libraries. 4) Active community and open source nature adapts them to new needs and technology trends.

    PHP and Python: Exploring Their Similarities and DifferencesPHP and Python: Exploring Their Similarities and DifferencesApr 19, 2025 am 12:21 AM

    PHP and Python are both high-level programming languages ​​that are widely used in web development, data processing and automation tasks. 1.PHP is often used to build dynamic websites and content management systems, while Python is often used to build web frameworks and data science. 2.PHP uses echo to output content, Python uses print. 3. Both support object-oriented programming, but the syntax and keywords are different. 4. PHP supports weak type conversion, while Python is more stringent. 5. PHP performance optimization includes using OPcache and asynchronous programming, while Python uses cProfile and asynchronous programming.

    PHP and Python: Different Paradigms ExplainedPHP and Python: Different Paradigms ExplainedApr 18, 2025 am 12:26 AM

    PHP is mainly procedural programming, but also supports object-oriented programming (OOP); Python supports a variety of paradigms, including OOP, functional and procedural programming. PHP is suitable for web development, and Python is suitable for a variety of applications such as data analysis and machine learning.

    PHP and Python: A Deep Dive into Their HistoryPHP and Python: A Deep Dive into Their HistoryApr 18, 2025 am 12:25 AM

    PHP originated in 1994 and was developed by RasmusLerdorf. It was originally used to track website visitors and gradually evolved into a server-side scripting language and was widely used in web development. Python was developed by Guidovan Rossum in the late 1980s and was first released in 1991. It emphasizes code readability and simplicity, and is suitable for scientific computing, data analysis and other fields.

    Choosing Between PHP and Python: A GuideChoosing Between PHP and Python: A GuideApr 18, 2025 am 12:24 AM

    PHP is suitable for web development and rapid prototyping, and Python is suitable for data science and machine learning. 1.PHP is used for dynamic web development, with simple syntax and suitable for rapid development. 2. Python has concise syntax, is suitable for multiple fields, and has a strong library ecosystem.

    PHP and Frameworks: Modernizing the LanguagePHP and Frameworks: Modernizing the LanguageApr 18, 2025 am 12:14 AM

    PHP remains important in the modernization process because it supports a large number of websites and applications and adapts to development needs through frameworks. 1.PHP7 improves performance and introduces new features. 2. Modern frameworks such as Laravel, Symfony and CodeIgniter simplify development and improve code quality. 3. Performance optimization and best practices further improve application efficiency.

    PHP's Impact: Web Development and BeyondPHP's Impact: Web Development and BeyondApr 18, 2025 am 12:10 AM

    PHPhassignificantlyimpactedwebdevelopmentandextendsbeyondit.1)ItpowersmajorplatformslikeWordPressandexcelsindatabaseinteractions.2)PHP'sadaptabilityallowsittoscaleforlargeapplicationsusingframeworkslikeLaravel.3)Beyondweb,PHPisusedincommand-linescrip

    How does PHP type hinting work, including scalar types, return types, union types, and nullable types?How does PHP type hinting work, including scalar types, return types, union types, and nullable types?Apr 17, 2025 am 12:25 AM

    PHP type prompts to improve code quality and readability. 1) Scalar type tips: Since PHP7.0, basic data types are allowed to be specified in function parameters, such as int, float, etc. 2) Return type prompt: Ensure the consistency of the function return value type. 3) Union type prompt: Since PHP8.0, multiple types are allowed to be specified in function parameters or return values. 4) Nullable type prompt: Allows to include null values ​​and handle functions that may return null values.

    See all articles

    Hot AI Tools

    Undresser.AI Undress

    Undresser.AI Undress

    AI-powered app for creating realistic nude photos

    AI Clothes Remover

    AI Clothes Remover

    Online AI tool for removing clothes from photos.

    Undress AI Tool

    Undress AI Tool

    Undress images for free

    Clothoff.io

    Clothoff.io

    AI clothes remover

    Video Face Swap

    Video Face Swap

    Swap faces in any video effortlessly with our completely free AI face swap tool!

    Hot Tools

    Atom editor mac version download

    Atom editor mac version download

    The most popular open source editor

    SublimeText3 Linux new version

    SublimeText3 Linux new version

    SublimeText3 Linux latest version

    SublimeText3 Mac version

    SublimeText3 Mac version

    God-level code editing software (SublimeText3)

    SublimeText3 English version

    SublimeText3 English version

    Recommended: Win version, supports code prompts!

    SAP NetWeaver Server Adapter for Eclipse

    SAP NetWeaver Server Adapter for Eclipse

    Integrate Eclipse with SAP NetWeaver application server.