<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>潘锦的空间 &#187; 自动加载</title>
	<atom:link href="https://www.phppan.com/tag/%e8%87%aa%e5%8a%a8%e5%8a%a0%e8%bd%bd/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.phppan.com</link>
	<description>SaaS SaaS架构 团队管理 技术管理 技术架构 PHP 内核 扩展 项目管理</description>
	<lastBuildDate>Sat, 25 Apr 2026 00:56:17 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=3.9.40</generator>
	<item>
		<title>PHP的类自动加载机制</title>
		<link>https://www.phppan.com/2011/08/php-class-autoload/</link>
		<comments>https://www.phppan.com/2011/08/php-class-autoload/#comments</comments>
		<pubDate>Mon, 15 Aug 2011 02:45:02 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[autoload]]></category>
		<category><![CDATA[PHP源码]]></category>
		<category><![CDATA[自动加载]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1448</guid>
		<description><![CDATA[在PHP5之前，各个PHP框架如果要实现类的自动加载，一般都是按照某种约定自己实现一个遍历目录，自动加载所有符 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p style="text-indent: 2em;">在PHP5之前，各个PHP框架如果要实现类的自动加载，一般都是按照某种约定自己实现一个遍历目录，自动加载所有符合约定规则的文件的类或函数。 当然，PHP5之前对面向对象的支持并不是太好，类的使用也没有现在频繁。 在PHP5后，当加载PHP类时，如果类所在文件没有被包含进来，或者类名出错，Zend引擎会自动调用__autoload 函数。此函数需要用户自己实现__autoload函数。 在PHP5.1.2版本后，可以使用spl_autoload_register函数自定义自动加载处理函数。当没有调用此函数，默认情况下会使用SPL自定义的spl_autoload函数。 看下面两个例子：</p>
<p style="text-indent: 2em;">1、 __autoload示例：</p>
<pre style="background-color: #333333; color: #ffffff; font: normal normal normal 13px/normal 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', 'Courier New', monospace; overflow-x: auto; overflow-y: auto; padding: 10px;"><span style="color: #cc7833;">function</span> __autoload<span style="color: #ffffff;">(</span><span style="color: #6d9cbe;">$class_name</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>
   <a style="color: #1299da; text-decoration: none;" href="http://www.php.net/echo"><span style="color: #e2392d;">echo</span></a> <span style="color: #56db3a;">'__autload class:'</span><span style="color: #e0882f;">,</span> <span style="color: #6d9cbe;">$class_name</span><span style="color: #e0882f;">,</span> <span style="color: #56db3a;">'&lt;br /&gt;'</span><span style="color: #e0882f;">;</span>
<span style="color: #ffffff;">}</span>

<span style="color: #cc7833;">new</span> Demo<span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span></pre>
<p style="text-indent: 2em;">以上的代码在最后会输出：__autload class:Demo。<br />
并在此之后报错显示： Fatal error: Class &#8216;Demo&#8217; not found</p>
<p style="text-indent: 2em;">2、spl_autoload_register示例：</p>
<pre style="background-color: #333333; color: #ffffff; font: normal normal normal 13px/normal 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', 'Courier New', monospace; overflow-x: auto; overflow-y: auto; padding: 10px;"><span style="color: #cc7833;">function</span> classLoader<span style="color: #ffffff;">(</span><span style="color: #6d9cbe;">$class_name</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>
    <a style="color: #1299da; text-decoration: none;" href="http://www.php.net/echo"><span style="color: #e2392d;">echo</span></a> <span style="color: #56db3a;">'SPL load class:'</span><span style="color: #e0882f;">,</span> <span style="color: #6d9cbe;">$class_name</span><span style="color: #e0882f;">,</span> <span style="color: #56db3a;">'&lt;br /&gt;'</span><span style="color: #e0882f;">;</span>
<span style="color: #ffffff;">}</span>

spl_autoload_register<span style="color: #ffffff;">(</span><span style="color: #56db3a;">'classLoader'</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>

<span style="color: #cc7833;">new</span> Demo<span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span></pre>
<p style="text-indent: 2em;">以上的代码在最后会输出：SPL load class:Demo。<br />
并在此之后报错显示： Fatal error: Class &#8216;Demo&#8217; not found</p>
<p style="text-indent: 2em;">以上的两个示例表明：当类不存在时（即需要的类不在类符号表），Zend引擎会将再调用一次用户定义的函数，如__autoload或spl_autoload_register注册的函数。 如果这两个方法同时存在，那么程序会调用哪一个呢？还是说两个都调用？看下面一个示例，你觉得会输出什么呢？</p>
<pre style="background-color: #333333; color: #ffffff; font: normal normal normal 13px/normal 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', 'Courier New', monospace; overflow-x: auto; overflow-y: auto; padding: 10px;"><span style="color: #cc7833;">function</span> __autoload<span style="color: #ffffff;">(</span><span style="color: #6d9cbe;">$class_name</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>
    <a style="color: #1299da; text-decoration: none;" href="http://www.php.net/echo"><span style="color: #e2392d;">echo</span></a> <span style="color: #56db3a;">'__autload class:'</span><span style="color: #e0882f;">,</span> <span style="color: #6d9cbe;">$class_name</span><span style="color: #e0882f;">,</span> <span style="color: #56db3a;">'&lt;br /&gt;'</span><span style="color: #e0882f;">;</span>
<span style="color: #ffffff;">}</span>

<span style="color: #cc7833;">function</span> classLoader<span style="color: #ffffff;">(</span><span style="color: #6d9cbe;">$class_name</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>
    <a style="color: #1299da; text-decoration: none;" href="http://www.php.net/echo"><span style="color: #e2392d;">echo</span></a> <span style="color: #56db3a;">'SPL load class:'</span><span style="color: #e0882f;">,</span> <span style="color: #6d9cbe;">$class_name</span><span style="color: #e0882f;">,</span> <span style="color: #56db3a;">'&lt;br /&gt;'</span><span style="color: #e0882f;">;</span>
<span style="color: #ffffff;">}</span>

spl_autoload_register<span style="color: #ffffff;">(</span><span style="color: #56db3a;">'classLoader'</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>

<span style="color: #cc7833;">new</span> Demo<span style="color: #ffffff;">(</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span></pre>
<p style="text-indent: 2em;">首先我们看__autload函数。从其命名格式来看，这是一个魔术方法。 虽然__autoload和__set、__tostring等类的魔法方法的常量定义在源码级别是一起的， 可是它并不是专属于某个类的魔法方法。它是所有的类共用的自动加载魔术方法。 它将作为一个全局函数存在。那么Zend引擎是如何在类没有找到时调用这个方法的呢？</p>
<p style="text-indent: 2em;">不管是使用new关键字创建类的实例，还是使用implement实现接口，或者继承某个类， 所有的这些操作都有可能调用__autoload函数。这几个操作在源码层都有一个共同点，它们在执行的时候都需要获取类的信息（接口在本质上也是一个类）。 它们在最终都会调用 zend_fetch_class (Zend/zend_execute_API.c)函数，这个函数本身没有多少内容，关键是它调用了zend_lookup_class_ex(Zend/zend_execute_API.c)函数， 这个函数就是类的自动加载的真相所在。</p>
<p style="text-indent: 2em;">在zend_lookup_class_ex函数中，我们看到程序会首先查询类符号表，如果存在类直接返回。如果不存在，就会执行我们所说的自动加载了。 这里针对__autoload函数和spl相关的函数都做了处理，并且以第一参数和第二参数传递给Zend引擎的函数调用函数zend_call_function。</p>
<p style="text-indent: 2em;">在zend_call_function函数中，它会判断第二参数是否存在函数，如果存在函数则只会调用第二个参数传递的函数（这里指SPL注册的函数）。 如果第二个函数没有值，则执行第一个参数传递过来的函数（这里指用户定义的__autoload函数）。 到这里，我想前面提到的两个方法同时存在的情况应该就有答案了。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2011/08/php-class-autoload/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
