自动加载的陷阱 class_exists缺省情况下会触发autoload,如果你没注意到这点的话很可能会吃亏,演示代码: spl_autoload_register(function($name) { echo $name; }); class_exists('foo'); 你可以通过in_array($name, get_declared_classes())函数来判断是
自动加载的陷阱
class_exists缺省情况下会触发autoload,如果你没注意到这点的话很可能会吃亏,演示代码:
spl_autoload_register(function($name) { echo $name; }); class_exists('foo');
你可以通过in_array($name, get_declared_classes())函数来判断是否存在相关的class,这样不会触发autoload,不过稍显笨重,其实class_exists()函数本身可以不触发autoload,方法是第二个参数:class_exists('foo', false);,不过老实说,当初设计的时候缺省值是true实在是个错误的决定。
BTW:method_exists也要注意,不过它没有类似class_exists那样能关闭autoload的参数控制,这一点在手册里已经明确写出来了,需要注意:
Note: Using this function will use any registered autoloaders if the class is not already known.
所以如果你不想触发autoload,那么在使用method_exists之前,必须确保对应的类已经加载,否则就没戏了。
缓存代码的重复味道
缓存在Web程序里必不可少,最常见的形式如下:
<p><span>01</span><span>class</span><span> Foo </span><span>extends</span><span> DAO<br></span><span>02</span><span> {<br></span><span>03</span><span>public</span><span>function</span><span> find_by_a()<br></span><span>04</span><span> {<br></span><span>05</span><span>$result</span><span>=</span><span>$this</span><span>-></span><span>cache</span><span>-></span><span>get(</span><span>'</span><span>cache_a</span><span>'</span><span>);<br></span><span>06</span><span><br></span><span>07</span><span>if</span><span> (</span><span>!</span><span>$result</span><span>) {<br></span><span>08</span><span>$result</span><span>=</span><span>$this</span><span>-></span><span>db</span><span>-></span><span>getAll(</span><span>'</span><span>select ... from ... where a ...</span><span>'</span><span>);<br></span><span>09</span><span><br></span><span>10</span><span>$this</span><span>-></span><span>cache</span><span>-></span><span>set(</span><span>'</span><span>cache_a</span><span>'</span><span>,</span><span>$result</span><span>);<br></span><span>11</span><span> }<br></span><span>12</span><span><br></span><span>13</span><span>return</span><span>$result</span><span>;<br></span><span>14</span><span> }<br></span><span>15</span><span><br></span><span>16</span><span>public</span><span>function</span><span> find_by_b()<br></span><span>17</span><span> {<br></span><span>18</span><span>$result</span><span>=</span><span>$this</span><span>-></span><span>cache</span><span>-></span><span>get(</span><span>'</span><span>cache_b</span><span>'</span><span>);<br></span><span>19</span><span><br></span><span>20</span><span>if</span><span> (</span><span>!</span><span>$result</span><span>) {<br></span><span>21</span><span>$result</span><span>=</span><span>$this</span><span>-></span><span>db</span><span>-></span><span>getAll(</span><span>'</span><span>select ... from ... where b ...</span><span>'</span><span>);<br></span><span>22</span><span><br></span><span>23</span><span>$this</span><span>-></span><span>cache</span><span>-></span><span>set(</span><span>'</span><span>cache_b</span><span>'</span><span>,</span><span>$result</span><span>);<br></span><span>24</span><span> }<br></span><span>25</span><span><br></span><span>26</span><span>return</span><span>$result</span><span>;<br></span><span>27</span><span> }<br></span><span>28</span><span> }</span></p>
这个代码很平常,实际情况中,多数人差不多都是这么写代码,先用某个键在缓存里取一下,如果没有就从数据库里实际查询一次,并且把结果缓存起来,这样的代码虽然不够健壮(没有捕捉可能存在的异常),不过本身并没有太大问题,但是若干个方法叠加起来,我们就能明显的感受到坏味道:重复!不说废话了哦,直接给出解决方案:
<p><span>01</span><span>abstract</span><span>class</span><span> DAO<br></span><span>02</span><span> {<br></span><span>03</span><span>public</span><span>function</span><span> getCache(</span><span>$key</span><span>,</span><span>$closure</span><span>)<br></span><span>04</span><span> {<br></span><span>05</span><span>$result</span><span>=</span><span>$this</span><span>-></span><span>cache</span><span>-></span><span>get(</span><span>$key</span><span>);<br></span><span>06</span><span><br></span><span>07</span><span>if</span><span> (</span><span>!</span><span>$result</span><span>) {<br></span><span>08</span><span>$result</span><span>=</span><span>$closure</span><span>();<br></span><span>09</span><span><br></span><span>10</span><span>$this</span><span>-></span><span>cache</span><span>-></span><span>set(</span><span>$key</span><span>,</span><span>$result</span><span>);<br></span><span>11</span><span> }<br></span><span>12</span><span><br></span><span>13</span><span>return</span><span>$result</span><span>;<br></span><span>14</span><span> }<br></span><span>15</span><span> }<br></span><span>16</span><span><br></span><span>17</span><span>class</span><span> Foo </span><span>extends</span><span> DAO<br></span><span>18</span><span> {<br></span><span>19</span><span>public</span><span>function</span><span> find_by_a()<br></span><span>20</span><span> {<br></span><span>21</span><span>return</span><span>$this</span><span>-></span><span>getCache(</span><span>'</span><span>cache_a</span><span>'</span><span>,</span><span>function</span><span>() {<br></span><span>22</span><span>return</span><span>$this</span><span>-></span><span>db</span><span>-></span><span>getAll(</span><span>'</span><span>select ... from ... where a ...</span><span>'</span><span>);<br></span><span>23</span><span> });<br></span><span>24</span><span> }<br></span><span>25</span><span><br></span><span>26</span><span>public</span><span>function</span><span> find_by_b()<br></span><span>27</span><span> {<br></span><span>28</span><span>return</span><span>$this</span><span>-></span><span>getCache(</span><span>'</span><span>cache_b</span><span>'</span><span>,</span><span>function</span><span>() {<br></span><span>29</span><span>return</span><span>$this</span><span>-></span><span>db</span><span>-></span><span>getAll(</span><span>'</span><span>select ... from ... where b ...</span><span>'</span><span>);<br></span><span>30</span><span> });<br></span><span>31</span><span> }<br></span><span>32</span><span> }</span></p>
代码有点简陋,通过把非公共代码提取成一个closure,传递给getCache方法,从而消除了重复的坏味道。