0

0

yii框架源码分析(二)

php中文网

php中文网

发布时间:2016-08-08 09:33:27

|

1568人浏览过

|

来源于php中文网

原创

转载请注明:TheViper http://www.cnblogs.com/TheViper/

上一篇主要分析了Yii::createWebApplication ( $config )->run ();的createWebApplication ( $config )部分,这篇分析后面的。

 run()也是不在CWebApplication里面,在CApplication 里。

<span> 1</span> <?<span>php </span><span> 2</span><span>abstract</span><span>class</span> CApplication <span>extends</span><span> CModule { </span><span> 3</span><span>private</span><span>$_id</span><span>; </span><span> 4</span><span>private</span><span>$_basePath</span><span>; </span><span> 5</span><span>abstract</span><span>public</span><span>function</span><span> processRequest(); </span><span> 6</span><span>public</span><span>function</span> __construct(<span>$config</span> = <span>null</span><span>) { </span><span> 7</span><span>if</span> (<span>is_string</span> ( <span>$config</span><span> )) </span><span> 8</span><span>$config</span> = <span>require</span> (<span>$config</span><span>); </span><span> 9</span> Yii::setApplication ( <span>$this</span> );<span>//</span><span>保存整个app实例</span><span>10</span><span>if</span> (<span>isset</span> ( <span>$config</span> ['basePath'<span>] )) { </span><span>11</span><span>$this</span>->setBasePath ( <span>$config</span> ['basePath'<span>] ); </span><span>12</span><span>unset</span> ( <span>$config</span> ['basePath'<span>] ); </span><span>13</span> } <span>else</span><span>14</span><span>$this</span>->setBasePath ( 'protected'<span> ); </span><span>15</span><span>//</span><span>设置别名,后面就可以用application表示basePath了</span><span>16</span> Yii::setPathOfAlias ( 'application', <span>$this</span>-><span>getBasePath () ); </span><span>17</span><span>//</span><span>钩子,模块 预 初始化时执行,子类实现。不过这时,配置还没有写入框架</span><span>18</span><span>$this</span>-><span>preinit (); </span><span>19</span><span>$this</span>-><span>registerCoreComponents (); </span><span>20</span><span>//</span><span>父类实现</span><span>21</span><span>$this</span>->configure ( <span>$config</span><span> ); </span><span>22</span><span>//</span><span>加载静态应用组件</span><span>23</span><span>$this</span>-><span>preloadComponents (); </span><span>24</span><span>//</span><span>这才开始初始化模块</span><span>25</span><span>$this</span>-><span>init (); </span><span>26</span><span> } </span><span>27</span><span>protected</span><span>function</span><span> registerCoreComponents() { </span><span>28</span><span>$components</span> = <span>array</span><span> ( </span><span>29</span> 'request' => <span>array</span><span> ( </span><span>30</span> 'class' => 'CHttpRequest' <span>31</span> ), <span>32</span> 'urlManager' => <span>array</span><span> ( </span><span>33</span> 'class' => 'CUrlManager' <span>34</span><span> ) </span><span>35</span><span> ); </span><span>36</span><span>37</span><span>$this</span>->setComponents ( <span>$components</span> );<span>//</span><span>父类实现</span><span>38</span><span> } </span><span>39</span><span>public</span><span>function</span><span> run() { </span><span>40</span><span>$this</span>-><span>processRequest (); </span><span>41</span><span> } </span><span>42</span><span>public</span><span>function</span><span> getId() { </span><span>43</span><span>if</span> (<span>$this</span>->_id !== <span>null</span><span>) </span><span>44</span><span>return</span><span>$this</span>-><span>_id; </span><span>45</span><span>else</span><span>46</span><span>return</span><span>$this</span>->_id = <span>sprintf</span> ( '%x', <span>crc32</span> ( <span>$this</span>->getBasePath () . <span>$this</span>-><span>name ) ); </span><span>47</span><span> } </span><span>48</span><span>public</span><span>function</span> setId(<span>$id</span><span>) { </span><span>49</span><span>$this</span>->_id = <span>$id</span><span>; </span><span>50</span><span> } </span><span>51</span><span>public</span><span>function</span><span> getBasePath() { </span><span>52</span><span>return</span><span>$this</span>-><span>_basePath; </span><span>53</span><span> } </span><span>54</span><span>public</span><span>function</span> setBasePath(<span>$path</span><span>) { </span><span>55</span><span>if</span> ((<span>$this</span>->_basePath = <span>realpath</span> ( <span>$path</span> )) === <span>false</span> || ! <span>is_dir</span> ( <span>$this</span>-><span>_basePath )) </span><span>56</span><span>return</span><span>; </span><span>57</span><span> } </span><span>58</span><span>public</span><span>function</span><span> getDb() { </span><span>59</span><span>return</span><span>$this</span>->getComponent ( 'db' );<span>//</span><span>父类实现</span><span>60</span><span> } </span><span>61</span><span>public</span><span>function</span><span> getUrlManager() { </span><span>62</span><span>return</span><span>$this</span>->getComponent ( 'urlManager'<span> ); </span><span>63</span><span> } </span><span>64</span><span>public</span><span>function</span><span> getController() { </span><span>65</span><span>return</span><span>null</span><span>; </span><span>66</span><span> } </span><span>67</span><span>public</span><span>function</span> getBaseUrl(<span>$absolute</span> = <span>false</span><span>) { </span><span>68</span><span>return</span><span>$this</span>->getRequest ()->getBaseUrl ( <span>$absolute</span><span> ); </span><span>69</span><span> } </span><span>70</span> }

run()又用了CWebApplication里面的processRequest()。薛强大哥(yii作者),架构要不要这样啊.裁剪后当然觉得这样的调用很没意思。

后面的主要在CWebApplication里了。

<span> 1</span> <?<span>php </span><span> 2</span><span>class</span> CWebApplication <span>extends</span><span> CApplication { </span><span> 3</span><span>public</span><span>$controllerNamespace</span><span>; </span><span> 4</span><span>private</span><span>$_controllerPath</span><span>; </span><span> 5</span><span>private</span><span>$_viewPath</span><span>; </span><span> 6</span><span>private</span><span>$_systemViewPath</span><span>; </span><span> 7</span><span>private</span><span>$_controller</span><span>; </span><span> 8</span><span>public</span><span>$controllerMap</span>=<span>array</span><span>(); </span><span> 9</span><span>public</span><span>function</span> processRequest() {<span>//</span><span>开始执行请求 </span><span>10</span><span> //获取urlManager组件,解析请求,得到controller/action这种格式的string, </span><span>11</span><span> //并且将隐藏参数与请求的参数一一对应,匹配起来,写入$_REQUEST中</span><span>12</span><span>$route</span> = <span>$this</span>->getUrlManager ()->parseUrl (<span>$this</span>-><span>getRequest()); </span><span>13</span><span>$this</span>->runController ( <span>$route</span><span> ); </span><span>14</span><span> } </span><span>15</span><span>public</span><span>function</span> getRequest() {<span>//</span><span>获取request组件</span><span>16</span><span>return</span><span>$this</span>->getComponent ( 'request'<span> ); </span><span>17</span><span> } </span><span>18</span><span>protected</span><span>function</span> registerCoreComponents() {<span>//</span><span>注册核心组件</span><span>19</span> parent::<span>registerCoreComponents (); </span><span>20</span><span> } </span><span>21</span><span>//</span><span>执行contronller</span><span>22</span><span>public</span><span>function</span> runController(<span>$route</span><span>) { </span><span>23</span><span>if</span> ((<span>$ca</span> = <span>$this</span>->createController ( <span>$route</span> )) !== <span>null</span><span>) { </span><span>24</span><span>list</span> ( <span>$controller</span>, <span>$actionID</span> ) = <span>$ca</span><span>; </span><span>25</span><span>$oldController</span> = <span>$this</span>-><span>_controller; </span><span>26</span><span>$this</span>->_controller = <span>$controller</span><span>; </span><span>27</span><span>$controller</span>->init ();<span>//</span><span>钩子,在执行action方法前调用,子类去实现</span><span>28</span><span>$controller</span>->run ( <span>$actionID</span> );<span>//</span><span>开始转入controller类中action方法的执行</span><span>29</span><span>$this</span>->_controller = <span>$oldController</span><span>; </span><span>30</span><span> } </span><span>31</span><span> } </span><span>32</span><span>//</span><span>创建controller类实例,从controller/action这种格式的string中解析出$controller, $actionID </span><span>33</span><span>public</span><span>function</span> createController(<span>$route</span>, <span>$owner</span> = <span>null</span><span>) { </span><span>34</span><span>if</span> (<span>$owner</span> === <span>null</span><span>) </span><span>35</span><span>$owner</span> = <span>$this</span><span>; </span><span>36</span><span>if</span> ((<span>$route</span> = <span>trim</span> ( <span>$route</span>, '/' )) === ''<span>) </span><span>37</span><span>$route</span> = <span>$owner</span>-><span>defaultController; </span><span>38</span><span>39</span><span>$route</span> .= '/'<span>; </span><span>40</span><span>while</span> ( (<span>$pos</span> = <span>strpos</span> ( <span>$route</span>, '/' )) !== <span>false</span><span> ) { </span><span>41</span><span>$id</span> = <span>substr</span> ( <span>$route</span>, 0, <span>$pos</span><span> ); </span><span>42</span><span>if</span> (! <span>preg_match</span> ( '/^w+$/', <span>$id</span><span> )) </span><span>43</span><span>return</span><span>null</span><span>; </span><span>44</span><span>$id</span> = <span>strtolower</span> ( <span>$id</span><span> ); </span><span>45</span><span>$route</span> = ( <span>string</span> ) <span>substr</span> ( <span>$route</span>, <span>$pos</span> + 1<span> ); </span><span>46</span><span>if</span> (! <span>isset</span> ( <span>$basePath</span> )) <span>//</span><span> first segment</span><span>47</span><span> { </span><span>48</span><span>$basePath</span> = <span>$owner</span>-><span>getControllerPath (); </span><span>49</span><span>$controllerID</span> = ''<span>; </span><span>50</span> } <span>else</span><span> { </span><span>51</span><span>$controllerID</span> .= '/'<span>; </span><span>52</span><span> } </span><span>53</span><span>$className</span> = <span>ucfirst</span> ( <span>$id</span> ) . 'Controller'<span>; </span><span>54</span><span>$classFile</span> = <span>$basePath</span> . DIRECTORY_SEPARATOR . <span>$className</span> . '.php'<span>; </span><span>55</span><span>56</span><span>if</span> (<span>is_file</span> ( <span>$classFile</span><span> )) { </span><span>57</span><span>if</span> (! <span>class_exists</span> ( <span>$className</span>, <span>false</span><span> )) </span><span>58</span><span>require</span> (<span>$classFile</span><span>); </span><span>59</span><span>if</span> (<span>class_exists</span> ( <span>$className</span>, <span>false</span> ) && <span>is_subclass_of</span> ( <span>$className</span>, 'CController'<span> )) { </span><span>60</span><span>$id</span> [0] = <span>strtolower</span> ( <span>$id</span> [0<span>] ); </span><span>61</span><span>return</span><span>array</span><span> ( </span><span>62</span><span>new</span><span>$className</span> ( <span>$controllerID</span> . <span>$id</span>, <span>$owner</span> === <span>$this</span> ? <span>null</span> : <span>$owner</span> ), <span>63</span><span>$this</span>->parseActionParams ( <span>$route</span><span> ) </span><span>64</span><span> ); </span><span>65</span><span> } </span><span>66</span><span>return</span><span>null</span><span>; </span><span>67</span><span> } </span><span>68</span><span>$controllerID</span> .= <span>$id</span><span>; </span><span>69</span><span>$basePath</span> .= DIRECTORY_SEPARATOR . <span>$id</span><span>; </span><span>70</span><span> } </span><span>71</span><span> } </span><span>72</span><span>protected</span><span>function</span> parseActionParams(<span>$pathInfo</span><span>) { </span><span>73</span><span>if</span> ((<span>$pos</span> = <span>strpos</span> ( <span>$pathInfo</span>, '/' )) !== <span>false</span><span>) { </span><span>74</span><span>$manager</span> = <span>$this</span>->getUrlManager ();<span>//</span><span>再次获取urlManager,在上面第一次调用中已经导入。</span><span>75</span><span>$manager</span>->parsePathInfo ( ( <span>string</span> ) <span>substr</span> ( <span>$pathInfo</span>, <span>$pos</span> + 1<span> ) ); </span><span>76</span><span>$actionID</span> = <span>substr</span> ( <span>$pathInfo</span>, 0, <span>$pos</span><span> ); </span><span>77</span><span>return</span><span>$manager</span>->caseSensitive ? <span>$actionID</span> : <span>strtolower</span> ( <span>$actionID</span><span> ); </span><span>78</span> } <span>else</span><span>79</span><span>return</span><span>$pathInfo</span><span>; </span><span>80</span><span> } </span><span>81</span><span>public</span><span>function</span><span> getControllerPath() { </span><span>82</span><span>if</span> (<span>$this</span>->_controllerPath !== <span>null</span><span>) </span><span>83</span><span>return</span><span>$this</span>-><span>_controllerPath; </span><span>84</span><span>else</span><span>85</span><span>return</span><span>$this</span>->_controllerPath = <span>$this</span>->getBasePath () . DIRECTORY_SEPARATOR . 'controllers'<span>; </span><span>86</span><span> } </span><span>87</span><span>//</span><span>两个钩子,子类去实现</span><span>88</span><span>public</span><span>function</span> beforeControllerAction(<span>$controller</span>, <span>$action</span><span>) { </span><span>89</span><span>return</span><span>true</span><span>; </span><span>90</span><span> } </span><span>91</span><span>public</span><span>function</span> afterControllerAction(<span>$controller</span>, <span>$action</span><span>) { </span><span>92</span><span> } </span><span>93</span><span>protected</span><span>function</span><span> init() { </span><span>94</span> parent::<span>init (); </span><span>95</span><span> } </span><span>96</span> }

对于$this->getUrlManager (),YiiBase里面有'CUrlManager' => 'CUrlManager.php'这个映射,说明是实例化了CUrlManager这个类。

 

<span> 1</span> <?<span>php </span><span> 2</span><span>class</span><span> CUrlManager { </span><span> 3</span><span>const</span> GET_FORMAT = 'get'<span>; </span><span> 4</span><span>public</span><span>$rules</span> = <span>array</span><span> (); </span><span> 5</span><span>public</span><span>$urlSuffix</span> = ''<span>; </span><span> 6</span><span>public</span><span>$caseSensitive</span> = <span>true</span><span>; </span><span> 7</span><span>public</span><span>$urlRuleClass</span> = 'CUrlRule'<span>; </span><span> 8</span><span>private</span><span>$_urlFormat</span> = self::<span>GET_FORMAT; </span><span> 9</span><span>private</span><span>$_rules</span> = <span>array</span><span> (); </span><span>10</span><span>private</span><span>$_baseUrl</span><span>; </span><span>11</span><span>protected</span><span>function</span><span> processRules() { </span><span>12</span><span>//</span><span>遍历自定义的请求匹配规则</span><span>13</span><span>foreach</span> ( <span>$this</span>->rules <span>as</span><span>$pattern</span> => <span>$route</span><span> ) { </span><span>14</span><span>//</span><span>对每一个规则创建CUrlRule实例</span><span>15</span><span>$this</span>->_rules [] = <span>$this</span>->createUrlRule ( <span>$route</span>, <span>$pattern</span><span> ); </span><span>16</span><span> } </span><span>17</span><span> } </span><span>18</span><span>protected</span><span>function</span> createUrlRule(<span>$route</span>, <span>$pattern</span><span>) { </span><span>19</span><span>if</span> (<span>is_array</span> ( <span>$route</span> ) && <span>isset</span> ( <span>$route</span> ['class'<span>] )) </span><span>20</span><span>return</span><span>$route</span><span>; </span><span>21</span><span>else</span><span> { </span><span>22</span><span>//</span><span>import第二个参数表示是否立即包含类文件。 如果为flase,则类文件仅在被使用时包含。 这个参数仅当使用一个类的路径 别名 时才会用到</span><span>23</span><span>$urlRuleClass</span> = Yii::import ( <span>$this</span>->urlRuleClass, <span>true</span><span> ); </span><span>24</span><span>//</span><span>创建CUrlRule实例</span><span>25</span><span>return</span><span>new</span><span>$urlRuleClass</span> ( <span>$route</span>, <span>$pattern</span><span> ); </span><span>26</span><span> } </span><span>27</span><span> } </span><span>28</span><span>//</span><span>类似于__construct()</span><span>29</span><span>public</span><span>function</span><span> init() { </span><span>30</span><span>$this</span>-><span>processRules (); </span><span>31</span><span> } </span><span>32</span><span>public</span><span>function</span> parseUrl(<span>$request</span><span>) { </span><span>33</span><span>//</span><span>获取请求</span><span>34</span><span>$rawPathInfo</span> = <span>$request</span>-><span>getPathInfo (); </span><span>35</span><span>$pathInfo</span> = <span>$this</span>->removeUrlSuffix ( <span>$rawPathInfo</span>, <span>$this</span>-><span>urlSuffix ); </span><span>36</span><span>foreach</span> ( <span>$this</span>->_rules <span>as</span><span>$i</span> => <span>$rule</span><span> ) { </span><span>37</span><span>if</span> ((<span>$r</span> = <span>$rule</span>->parseUrl ( <span>$this</span>, <span>$pathInfo</span>, <span>$rawPathInfo</span> )) !== <span>false</span><span>) { </span><span>38</span><span>return</span><span>$r</span><span>; </span><span>39</span><span> } </span><span>40</span><span> } </span><span>41</span><span>return</span><span>$pathInfo</span><span>; </span><span>42</span><span> } </span><span>43</span><span>//</span><span>解析请求,将请求参数写入$_REQUEST</span><span>44</span><span>public</span><span>function</span> parsePathInfo(<span>$pathInfo</span><span>) { </span><span>45</span><span>if</span> (<span>$pathInfo</span> === ''<span>) </span><span>46</span><span>return</span><span>; </span><span>47</span><span>$segs</span> = <span>explode</span> ( '/', <span>$pathInfo</span> . '/'<span> ); </span><span>48</span><span>$n</span> = <span>count</span> ( <span>$segs</span><span> ); </span><span>49</span><span>for</span>(<span>$i</span> = 0; <span>$i</span> < <span>$n</span> - 1; <span>$i</span> += 2<span>) { </span><span>50</span><span>$key</span> = <span>$segs</span> [<span>$i</span><span>]; </span><span>51</span><span>if</span> (<span>$key</span> === ''<span>) </span><span>52</span><span>continue</span><span>; </span><span>53</span><span>$value</span> = <span>$segs</span> [<span>$i</span> + 1<span>]; </span><span>54</span><span>if</span> ((<span>$pos</span> = <span>strpos</span> ( <span>$key</span>, '[' )) !== <span>false</span> && (<span>$m</span> = <span>preg_match_all</span> ( '/[(.*?)]/', <span>$key</span>, <span>$matches</span> )) > 0<span>) { </span><span>55</span><span>$name</span> = <span>substr</span> ( <span>$key</span>, 0, <span>$pos</span><span> ); </span><span>56</span><span>for</span>(<span>$j</span> = <span>$m</span> - 1; <span>$j</span> >= 0; -- <span>$j</span><span>) { </span><span>57</span><span>if</span> (<span>$matches</span> [1] [<span>$j</span>] === ''<span>) </span><span>58</span><span>$value</span> = <span>array</span><span> ( </span><span>59</span><span>$value</span><span>60</span><span> ); </span><span>61</span><span>else</span><span>62</span><span>$value</span> = <span>array</span><span> ( </span><span>63</span><span>$matches</span> [1] [<span>$j</span>] => <span>$value</span><span>64</span><span> ); </span><span>65</span><span> } </span><span>66</span><span>if</span> (<span>isset</span> ( <span>$_GET</span> [<span>$name</span>] ) && <span>is_array</span> ( <span>$_GET</span> [<span>$name</span><span>] )) </span><span>67</span><span>$value</span> = CMap::mergeArray ( <span>$_GET</span> [<span>$name</span>], <span>$value</span><span> ); </span><span>68</span><span>$_REQUEST</span> [<span>$name</span>] = <span>$_GET</span> [<span>$name</span>] = <span>$value</span><span>; </span><span>69</span> } <span>else</span><span> { </span><span>70</span><span>$_REQUEST</span> [<span>$key</span>] = <span>$_GET</span> [<span>$key</span>] = <span>$value</span><span>; </span><span>71</span><span> } </span><span>72</span><span> } </span><span>73</span><span> } </span><span>74</span><span>//</span><span>去除请求后缀,如video/broadcast.html=>video/broadcast </span><span>75</span><span>public</span><span>function</span> removeUrlSuffix(<span>$pathInfo</span>, <span>$urlSuffix</span><span>) { </span><span>76</span><span>if</span> (<span>$urlSuffix</span> !== '' && <span>substr</span> ( <span>$pathInfo</span>, - <span>strlen</span> ( <span>$urlSuffix</span> ) ) === <span>$urlSuffix</span><span>) </span><span>77</span><span>return</span><span>substr</span> ( <span>$pathInfo</span>, 0, - <span>strlen</span> ( <span>$urlSuffix</span><span> ) ); </span><span>78</span><span>else</span><span>79</span><span>return</span><span>$pathInfo</span><span>; </span><span>80</span><span> } </span><span>81</span> }

yii在创建组件的时候,在调用了CModule的getComponent($id, $createIfNull = true)里面调用了$component->init ();。

所以这里进入init(),然后processRules()遍历自定义的请求匹配规则。如

<span> 1</span> 'urlManager' => <span>array</span><span> ( </span><span> 2</span> 'urlFormat' => 'path', <span> 3</span> 'rules' => <span>array</span><span> ( </span><span> 4</span> 'comment_reply/<a:d+>/<ci:d+>' => 'reply/load_comment_reply', <span> 5</span> 'b/<id:d+>' => <span>array</span><span> ( </span><span> 6</span> 'video/broadcast', <span> 7</span> 'urlSuffix' => '.html' <span> 8</span> ), <span> 9</span> 'c/<list_start:d+>' => 'video/list_more_video', <span>10</span> 'u/reg' => 'user/reg', <span>11</span> 'v/upload' => 'video/upload_video', <span>12</span> 'login' => 'user/to_login', <span>13</span> 'show_chanel/<chanel_id:d+>' => 'show/chanel' , <span>14</span> 'show/<show_id:d+>' => 'show/show', <span>15</span><span> ) </span><span>16</span> ) 

 $this->_rules [] = $this->createUrlRule ( $route, $pattern );对每一个规则创建CUrlRule实例,并保存。

<span> 1</span> <?<span>php </span><span> 2</span><span>class</span><span> CUrlRule { </span><span> 3</span><span>public</span><span>$urlSuffix</span><span>; </span><span> 4</span><span>public</span><span>$defaultParams</span> = <span>array</span><span> (); </span><span> 5</span><span>public</span><span>$route</span><span>; </span><span> 6</span><span>public</span><span>$routePattern</span><span>; </span><span> 7</span><span>public</span><span>$pattern</span><span>; </span><span> 8</span><span>public</span><span>$template</span><span>; </span><span> 9</span><span>public</span><span>$params</span> = <span>array</span><span> (); </span><span>10</span><span>//</span><span>根据自定义规则构建匹配参数的正则表达式。</span><span>11</span><span>public</span><span>function</span> __construct(<span>$route</span>, <span>$pattern</span><span>) { </span><span>12</span><span>if</span> (<span>is_array</span> ( <span>$route</span><span> )) { </span><span>13</span><span>foreach</span> ( <span>array</span><span> ( </span><span>14</span> 'urlSuffix', <span>15</span> 'caseSensitive', <span>16</span> 'defaultParams', <span>17</span> ) <span>as</span><span>$name</span><span> ) { </span><span>18</span><span>if</span> (<span>isset</span> ( <span>$route</span> [<span>$name</span><span>] )) </span><span>19</span><span>$this</span>-><span>$name</span> = <span>$route</span> [<span>$name</span><span>]; </span><span>20</span><span> } </span><span>21</span><span>if</span> (<span>isset</span> ( <span>$route</span> ['pattern'<span>] )) </span><span>22</span><span>$pattern</span> = <span>$route</span> ['pattern'<span>]; </span><span>23</span><span>$route</span> = <span>$route</span> [0<span>]; </span><span>24</span><span> } </span><span>25</span><span>$this</span>->route = <span>trim</span> ( <span>$route</span>, '/'<span> ); </span><span>26</span><span>27</span><span>$tr2</span> ['/'] = <span>$tr</span> ['/'] = '\/'<span>; </span><span>28</span><span>$tr</span> ['.'] = '\.'<span>; </span><span>29</span><span>30</span><span>$this</span>->hasHostInfo = ! <span>strncasecmp</span> ( <span>$pattern</span>, 'http://', 7 ) || ! <span>strncasecmp</span> ( <span>$pattern</span>, 'https://', 8<span> ); </span><span>31</span><span>32</span><span>if</span> (<span>preg_match_all</span> ( '/<(w+):?(.*?)?>/', <span>$pattern</span>, <span>$matches</span><span> )) { </span><span>33</span><span>$tokens</span> = <span>array_combine</span> ( <span>$matches</span> [1], <span>$matches</span> [2<span>] ); </span><span>34</span><span>foreach</span> ( <span>$tokens</span><span>as</span><span>$name</span> => <span>$value</span><span> ) { </span><span>35</span><span>if</span> (<span>$value</span> === ''<span>) </span><span>36</span><span>$value</span> = '[^/]+'<span>; </span><span>37</span><span>$tr</span> ["<<span>$name</span>>"] = "(?P<<span>$name</span>><span>$value</span>)"<span>; </span><span>38</span><span>//</span><span>取出自定义规则中隐藏的参数,保存</span><span>39</span><span>if</span> (<span>isset</span> ( <span>$this</span>->references [<span>$name</span><span>] )) </span><span>40</span><span>$tr2</span> ["<<span>$name</span>>"] = <span>$tr</span> ["<<span>$name</span>>"<span>]; </span><span>41</span><span>else</span><span>42</span><span>$this</span>->params [<span>$name</span>] = <span>$value</span><span>; </span><span>43</span><span> } </span><span>44</span><span> } </span><span>45</span><span>$p</span> = <span>rtrim</span> ( <span>$pattern</span>, '*'<span> ); </span><span>46</span><span>$this</span>->append = <span>$p</span> !== <span>$pattern</span><span>; </span><span>47</span><span>$p</span> = <span>trim</span> ( <span>$p</span>, '/'<span> ); </span><span>48</span><span>$this</span>->template = <span>preg_replace</span> ( '/<(w+):?.*?>/', '<$1>', <span>$p</span><span> ); </span><span>49</span><span>$this</span>->pattern = '/^' . <span>strtr</span> ( <span>$this</span>->template, <span>$tr</span> ) . '/'<span>; </span><span>50</span><span>//</span><span>合成匹配的正则表达式</span><span>51</span><span>if</span> (<span>$this</span>-><span>append) </span><span>52</span><span>$this</span>->pattern .= '/u'<span>; </span><span>53</span><span>else</span><span>54</span><span>$this</span>->pattern .= '$/u'<span>; </span><span>55</span><span> } </span><span>56</span><span>//</span><span>根据正则表达式和请求,将隐藏参数与请求参数一一匹配,保存$_REQUEST</span><span>57</span><span>public</span><span>function</span> parseUrl(<span>$manager</span>, <span>$pathInfo</span>, <span>$rawPathInfo</span><span>) { </span><span>58</span><span>if</span> (<span>$this</span>->urlSuffix !== <span>null</span><span>) { </span><span>59</span><span>$pathInfo</span> = <span>$manager</span>->removeUrlSuffix ( <span>$rawPathInfo</span>, <span>$this</span>-><span>urlSuffix ); </span><span>60</span><span> } </span><span>61</span><span>$pathInfo</span> .= '/'<span>; </span><span>62</span><span>if</span> (<span>preg_match</span> ( <span>$this</span>->pattern, <span>$pathInfo</span>, <span>$matches</span><span> )) { </span><span>63</span><span>foreach</span> ( <span>$this</span>->defaultParams <span>as</span><span>$name</span> => <span>$value</span><span> ) { </span><span>64</span><span>if</span> (! <span>isset</span> ( <span>$_GET</span> [<span>$name</span><span>] )) </span><span>65</span><span>$_REQUEST</span> [<span>$name</span>] = <span>$_GET</span> [<span>$name</span>] = <span>$value</span><span>; </span><span>66</span><span> } </span><span>67</span><span>$tr</span> = <span>array</span><span> (); </span><span>68</span><span>foreach</span> ( <span>$matches</span><span>as</span><span>$key</span> => <span>$value</span><span> ) { </span><span>69</span><span>if</span> (<span>isset</span> ( <span>$this</span>->references [<span>$key</span><span>] )) </span><span>70</span><span>$tr</span> [<span>$this</span>->references [<span>$key</span>]] = <span>$value</span><span>; </span><span>71</span><span>elseif</span> (<span>isset</span> ( <span>$this</span>->params [<span>$key</span><span>] )) </span><span>72</span><span>$_REQUEST</span> [<span>$key</span>] = <span>$_GET</span> [<span>$key</span>] = <span>$value</span><span>; </span><span>73</span><span> } </span><span>74</span><span>if</span> (<span>$pathInfo</span> !== <span>$matches</span> [0]) <span>//</span><span>如果还有另外的请求参数</span><span>75</span><span>$manager</span>->parsePathInfo ( <span>ltrim</span> ( <span>substr</span> ( <span>$pathInfo</span>, <span>strlen</span> ( <span>$matches</span> [0] ) ), '/'<span> ) ); </span><span>76</span><span>return</span><span>$this</span>-><span>route; </span><span>77</span> } <span>else</span><span>78</span><span>return</span><span>false</span><span>; </span><span>79</span><span> } </span><span>80</span> }

CUrlRule中的parseUrl($manager, $pathInfo, $rawPathInfo)这里暂时还没用到。

然后回到CWebApplication中的¥route=$this->getUrlManager ()->parseUrl ($this->getRequest());。后面parseUrl开始解析请求了。

转到CUrlManager的parseUrl($request),遍历创建CUrlRule过程中保存的匹配规则,再在CUrlRule里面用CUrlRule的parseUrl($manager, $pathInfo, $rawPathInfo)将隐藏参数与请求参数一一匹配,保存$_REQUEST.

比如:

'b/' => array (
  'video/broadcast',
  'urlSuffix' => '.html'
)

我的请求是b/1.html,就会被解析成video/broadcast?id=1.而最终的$route就是这个。

最后附上,裁剪的yii http://files.cnblogs.com/TheViper/framework.zip

下一篇

以上就介绍了yii框架源码分析(二),包括了yii框架源码方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

Python异步编程与Asyncio高并发应用实践
Python异步编程与Asyncio高并发应用实践

本专题围绕 Python 异步编程模型展开,深入讲解 Asyncio 框架的核心原理与应用实践。内容包括事件循环机制、协程任务调度、异步 IO 处理以及并发任务管理策略。通过构建高并发网络请求与异步数据处理案例,帮助开发者掌握 Python 在高并发场景中的高效开发方法,并提升系统资源利用率与整体运行性能。

46

2026.03.12

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

178

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

51

2026.03.10

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

92

2026.03.09

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

102

2026.03.06

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

227

2026.03.05

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

532

2026.03.04

AI安装教程大全
AI安装教程大全

2026最全AI工具安装教程专题:包含各版本AI绘图、AI视频、智能办公软件的本地化部署手册。全篇零基础友好,附带最新模型下载地址、一键安装脚本及常见报错修复方案。每日更新,收藏这一篇就够了,让AI安装不再报错!

171

2026.03.04

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
JavaScript高级框架设计视频教程
JavaScript高级框架设计视频教程

共22课时 | 3.7万人学习

AngularJS教程
AngularJS教程

共24课时 | 4.2万人学习

CSS3实现按钮特效视频教程
CSS3实现按钮特效视频教程

共15课时 | 3.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号