PHP学习 之 autoload

本文的示例代码参考autoload

目录

环境

phpbrew

sudo apt install -y \
  php7.0 \
  php7.0-curl \
  php7.0-json \
  php7.0-cgi \
  php7.0-fpm \
  autoconf \
  automake \
  libxml2-dev \
  libcurl4-openssl-dev \
  libssl-dev \
  openssl \
  gettext \
  libicu-dev \
  libmcrypt-dev \
  libmcrypt4 \
  libbz2-dev \
  libreadline-dev \
  build-essential \
  libmhash-dev \
  libmhash2 \
  libxslt1-dev

相关依赖参考 Requirement - Ubuntu 16.04

curl -L -O https://github.com/phpbrew/phpbrew/raw/master/phpbrew

chmod +x phpbrew && sudo mv phpbrew /usr/local/bin/phpbrew

phpbrew init

cat ~/.phpbrew/bashrc >> ~/.bashrc && . ~/.bashrc
phpbrew known

phpbrew install 7.1.0

phpbrew use 7.1.0 && php -v

开始

vim startup.php
<?php
class Person
{
    var $name, $age;

    function __construct($name, $age)
    {
        $this->name = $name;
        $this->age = $age;
    }
}

$person = new Person("David", 6);
var_dump($person);

PHP语法参考 X分钟速成Y - 其中 Y=PHP

php startup.php
object(Person)#1 (2) {
  ["name"]=>
  string(5) "David"
  ["age"]=>
  int(6)
}

没有autoload

vim Person.php
<?php
class Person
{
    var $name, $age;

    function __construct($name, $age)
    {
        $this->name = $name;
        $this->age = $age;
    }
}
vim no_autoload.php
<?php
require_once "Person.php";

$person = new Person("David", 6);
var_dump($person);
php no_autoload.php
object(Person)#1 (2) {
  ["name"]=>
  string(5) "David"
  ["age"]=>
  int(6)
}

include与require的区别参考 PHP中include和require的区别详解 / php中return,require,include加括号和不加括号的区别

PHP autoload

vim php_autoload.php
<?php
function __autoload($class_name)
{
    echo "__autoload classname: ".$class_name."\n";

    $class_path = "./".$class_name.'.php';
    if(file_exists($class_path))
    {
        require_once $class_path;
    }
    else
    {
        echo 'class file'.$class_path.'not found!';
    }
}

$person = new Person("David", 6);
var_dump($person);
php php_autoload.php
__autoload classname: Person
object(Person)#1 (2) {
  ["name"]=>
  string(5) "David"
  ["age"]=>
  int(6)
}

SPL autoload

The Standard PHP Library(SPL) is a collection of interfaces and classes that are meant to solve common problems

vim  spl_autoload.php
<?php
function autoload_in_dir($class_name, $dir) {
    echo "autoload in ".$dir." classname: ".$class_name."\n";

    $class_path = $dir.$class_name.'.php';
    if(file_exists($class_path))
    {
        require_once $class_path;
    }
    else
    {
        echo 'class file'.$class_path.'not found!';
    }
}

function autoload_in_current_dir($class_name) {
    autoload_in_dir($class_name, "./");
}

spl_autoload_register("autoload_in_current_dir");

$person = new Person("David", 6);
var_dump($person);
php spl_autoload.php
autoload in ./ classname: Person
object(Person)#1 (2) {
  ["name"]=>
  string(5) "David"
  ["age"]=>
  int(6)
}
vim  spl_autoload.php
<?php
function autoload_in_dir($class_name, $dir) {
    echo "autoload in ".$dir." classname: ".$class_name."\n";

    $class_path = $dir.$class_name.'.php';
    if(file_exists($class_path))
    {
        require_once $class_path;
    }
    else
    {
        echo 'class file'.$class_path.'not found!';
    }
}

function autoload_in_current_dir($class_name) {
    autoload_in_dir($class_name, "./");
}

function autoload_in_parent_dir($class_name) {
    autoload_in_dir($class_name, "../");
}

spl_autoload_register("autoload_in_current_dir");
spl_autoload_unregister("autoload_in_current_dir");
spl_autoload_register("autoload_in_parent_dir");

$person = new Person("David", 6);
var_dump($person);
php spl_autoload.php
autoload in ../ classname: Person
class file../Person.phpnot found!PHP Fatal error:  Uncaught Error: Class 'Person' not found in /Users/kevin/Workspace/php-tutorial/autoload/spl_autoload.php:28

Composer autoload

Composer详细介绍参考 Composer 中文文档

composer.json

cat composer.json
# 其他略过
"autoload": {
    "psr-4": {
        "Base\\": "module/Base/"
    }
},
# 其他略过

Composer autoload参考 Composer 中文文档 - 基本用法

vendor/autoload.php

cat vendor/autoload.php
<?php

// autoload.php @generated by Composer

require_once __DIR__ . '/composer/autoload_real.php';

return ComposerAutoloaderInit2d9e6983d02eaab8b6b26ee749ae9efa::getLoader();

vendor/composer/autoload_real.php

cat vendor/composer/autoload_real.php
<?php

// autoload_real.php @generated by Composer

class ComposerAutoloaderInit2d9e6983d02eaab8b6b26ee749ae9efa
{
    private static $loader;

    public static function loadClassLoader($class)
    {
        if ('Composer\Autoload\ClassLoader' === $class) {
            require __DIR__ . '/ClassLoader.php';
        }
    }

    public static function getLoader()
    {
        self::$loader = $loader = new \Composer\Autoload\ClassLoader();

        $map = require __DIR__ . '/autoload_psr4.php';
        foreach ($map as $namespace => $path) {
            $loader->setPsr4($namespace, $path);
        }

        $loader->register(true);

        return $loader;
    }
}

为叙述问题方便 这里只保留核心代码 以下也相同处理

vendor/composer/autoload_psr4.php

cat vendor/composer/autoload_psr4.php
<?php

// autoload_psr4.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'Base\\' => array($baseDir . '/module/Base'),
);

vendor/composer/ClassLoader.php

cat vendor/composer/ClassLoader.php
<?php

namespace Composer\Autoload;

class ClassLoader
{
    // PSR-4
    private $prefixLengthsPsr4 = array();
    private $prefixDirsPsr4 = array();
    private $fallbackDirsPsr4 = array();

    public function setPsr4($prefix, $paths)
    {
        if (!$prefix) {
            $this->fallbackDirsPsr4 = (array) $paths;
        } else {
            $length = strlen($prefix);
            if ('\\' !== $prefix[$length - 1]) {
                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
            }
            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
            $this->prefixDirsPsr4[$prefix] = (array) $paths;
        }
    }

    public function register($prepend = false)
    {
        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
    }

    public function loadClass($class)
    {
        if ($file = $this->findFile($class)) {
            includeFile($file);

            return true;
        }
    }
}

参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容