Heim > Artikel > Backend-Entwicklung > Quellcode-Analyse von YII (2)
Im vorherigen Artikel wurde der Prozess von Yii kurz analysiert, von der Erstellung einer Anwendung bis zur Ausgabe der Ergebnisse auf dem Bildschirm. Dieses Mal werde ich etwas komplizierteres machen und mich auf die Ausgabe konzentrieren. Es handelt sich nicht mehr um eine einfache „Hallo Welt“-Zeile, sondern muss von der Ansichtsebene verarbeitet werden.
Noch im Demoverzeichnis wählen wir dieses Mal Hangman, ein einfaches Ratespiel. Die alte Regel lautet, am Eingang zu beginnen.
index.php:
<?<span>php </span><span>//</span><span> change the following paths if necessary</span> <span>$yii</span>=<span>dirname</span>(<span>__FILE__</span>).'/../../framework/yii.php'<span>; </span><span>$config</span>=<span>dirname</span>(<span>__FILE__</span>).'/protected/config/main.php'<span>; </span><span>//</span><span> remove the following line when in production mode // defined('YII_DEBUG') or define('YII_DEBUG',true);</span> <span>require_once</span>(<span>$yii</span><span>); Yii</span>::createWebApplication(<span>$config</span>)->run();
Im Vergleich zur Helloworld-Anwendung gibt es diesmal main.php. Öffnen Sie main und schauen Sie sich den Quellcode an:
<?<span>php </span><span>return</span> <span>array</span><span>( </span>'name'=>'Hangman Game', 'defaultController'=>'game', 'components'=><span>array</span><span>( </span>'urlManager'=><span>array</span><span>( </span>'urlFormat'=>'path', 'rules'=><span>array</span><span>( </span>'game/guess/<g:\w>'=>'game/guess',<span> )</span>,<span> )</span>,<span> )</span>,<span> );</span>
In unseren zukünftigen tatsächlichen Projekten werden häufig Konfigurationsdateien verwendet, daher denke ich, dass es notwendig ist, die yii-Konfigurationsdatei --main.php
zu verstehen'name'=>'Dies definiert normalerweise den Titel der Website', das ist der Titel, der auf der Webseite angezeigt wird, wenn wir index.php öffnen.
'defaultController'=>'Dies ist der Standard-Controller', der vom System verwendet wird, wenn hinter unserer index.php kein Controller angegeben ist, ist der Standardwert site
'components'=>'Hier sind die Parameter der Komponente, konfiguriert mit einem mehrdimensionalen Array. „Spezifische Parameter finden Sie im yii-Handbuch.
Yii::createWebApplication($config)->run(); Wir haben es letztes Mal im Detail analysiert, hier ist eine einfache Anleitung:
CWebApplication.php -> CApplication.php -> __construct($config) :
<span>$this</span>-><span>preinit(); </span><span>$this</span>-><span>initSystemHandlers(); </span><span>$this</span>-><span>registerCoreComponents(); </span><span>$this</span>->configure(<span>$config</span><span>); </span><span>$this</span>->attachBehaviors(<span>$this</span>-><span>behaviors); </span><span>$this</span>-><span>preloadComponents(); </span><span>$this</span>->init();
Das letzte Mal hatten wir keinen Konfigurationsprozess, also hat $this->configure($config) nichts getan, aber dieses Mal gibt es Konfigurationsparameter, also schauen wir uns an, welche Operationen yii durchgeführt hat:
CApplication selbst implementiert die configure-Methode nicht, sondern wird von CModule.php geerbt:
<span>public</span> <span>function</span> configure(<span>$config</span><span>) { </span><span>if</span>(<span>is_array</span>(<span>$config</span><span>)) { </span><span>foreach</span>(<span>$config</span> <span>as</span> <span>$key</span>=><span>$value</span><span>) </span><span>$this</span>-><span>$key</span>=<span>$value</span><span>; } }</span>
Der Code ist sehr einfach, das heißt, der Schlüssel des Konfigurationsparameters wird als Attributname der Klasse und der Wert als Attributwert der Klasse verwendet. Führen Sie nach Abschluss dieses Vorgangs die Ausführungsmethode für CApplication aus.
<span>public</span> <span>function</span><span> run() { </span><span>if</span>(<span>$this</span>->hasEventHandler('onBeginRequest'<span>)) </span><span>$this</span>->onBeginRequest(<span>new</span> CEvent(<span>$this</span><span>)); </span><span>register_shutdown_function</span>(<span>array</span>(<span>$this</span>,'end'),0,<span>false</span><span>); </span><span>$this</span>-><span>processRequest(); </span><span>if</span>(<span>$this</span>->hasEventHandler('onEndRequest'<span>)) </span><span>$this</span>->onEndRequest(<span>new</span> CEvent(<span>$this</span><span>)); }</span>
Wie bereits erwähnt, konzentrieren Sie sich hier einfach auf $this->processRequest(); Das Ergebnis der Operation ist die Ausführung von $this->runController('');
<span>public</span> <span>function</span> runController(<span>$route</span><span>) { </span><span>if</span>((<span>$ca</span>=<span>$this</span>->createController(<span>$route</span>))!==<span>null</span><span>) { </span><span>list</span>(<span>$controller</span>,<span>$actionID</span>)=<span>$ca</span><span>; </span><span>$oldController</span>=<span>$this</span>-><span>_controller; </span><span>$this</span>->_controller=<span>$controller</span><span>; </span><span>$controller</span>-><span>init(); </span><span>$controller</span>->run(<span>$actionID</span><span>); </span><span>$this</span>->_controller=<span>$oldController</span><span>; } </span><span>else</span> <span>throw</span> <span>new</span> CHttpException(404,Yii::t('yii','Unable to resolve the request "{route}".', <span>array</span>('{route}'=><span>$route</span>===''?<span>$this</span>->defaultController:<span>$route</span><span>))); }</span>Da die URL index.php lautet und keine Parameter dahinter stehen, wird der Standard-Controller verwendet, das ist das Spiel, das wir in main.php festgelegt haben. Also ist $controller wie oben beschrieben gleich controllers/gameController.php Aus dieser Quellcode-Analyse können wir erkennen, dass, wenn in gameController.php keine Init-Methode vorhanden ist, die in der übergeordneten Klasse definierte Standardmethode verwendet wird (eigentlich eine leere Methode),
$controller->run($actionID<span>); == gameController</span>->run(''); gameController上没有实现run方法,于是又是去父类中找runAus der Klasse „GameController erweitert CController“ ist ersichtlich, dass die übergeordnete Klasse CController ist. Suchen Sie die entsprechende Ausführungsmethode:
<span>public</span> <span>function</span> run(<span>$actionID</span><span>) { </span><span>if</span>((<span>$action</span>=<span>$this</span>->createAction(<span>$actionID</span>))!==<span>null</span><span>) { </span><span>if</span>((<span>$parent</span>=<span>$this</span>->getModule())===<span>null</span><span>) </span><span>$parent</span>=Yii::<span>app(); </span><span>if</span>(<span>$parent</span>->beforeControllerAction(<span>$this</span>,<span>$action</span><span>)) { </span><span>$this</span>->runActionWithFilters(<span>$action</span>,<span>$this</span>-><span>filters()); </span><span>$parent</span>->afterControllerAction(<span>$this</span>,<span>$action</span><span>); } } </span><span>else</span> <span>$this</span>->missingAction(<span>$actionID</span><span>); }</span>Es wurde bereits analysiert. Wenn es nicht angegeben ist, ist es der Standardparameter. Dann ist $actionID zu diesem Zeitpunkt leer und actionID ist die in gameController definierte Standardaktion: public $defaultAction='play';
runActionWithFilters ---> runAction --> $action->runWithParams<br>这里的$action 需要从CAction -> CInlineAction中去找<br>
<span>public</span> <span>function</span> runWithParams(<span>$params</span><span>) { </span><span>$methodName</span>='action'.<span>$this</span>-><span>getId(); </span><span>$controller</span>=<span>$this</span>-><span>getController(); </span><span>$method</span>=<span>new</span> ReflectionMethod(<span>$controller</span>, <span>$methodName</span><span>); </span><span>if</span>(<span>$method</span>->getNumberOfParameters()>0<span>) </span><span>return</span> <span>$this</span>->runWithParamsInternal(<span>$controller</span>, <span>$method</span>, <span>$params</span><span>); </span><span>else</span> <span>return</span> <span>$controller</span>-><span>$methodName</span><span>(); }</span>Nachdem wir so viele Prozesse durchlaufen haben, ähnelt es dem Prozess „Hallo Welt“. Nach der letzten Analyse können wir wissen, dass hier ausgeführt wird
$controller->$methodName<span>(); 也就是GameController->actionPlay()<br>到此,我们本节的重点才真正开始:<br></span>
<span>public</span> <span>function</span><span> actionPlay() { </span><span>static</span> <span>$levels</span>=<span>array</span><span>( </span>'10'=>'Easy game; you are allowed 10 misses.', '5'=>'Medium game; you are allowed 5 misses.', '3'=>'Hard game; you are allowed 3 misses.',<span> ); </span><span>//</span><span> if a difficulty level is correctly chosen</span> <span>if</span>(<span>isset</span>(<span>$_POST</span>['level']) && <span>isset</span>(<span>$levels</span>[<span>$_POST</span>['level'<span>]])) { </span><span>$this</span>->word=<span>$this</span>-><span>generateWord(); </span><span>$this</span>->guessWord=<span>str_repeat</span>('_',<span>strlen</span>(<span>$this</span>-><span>word)); </span><span>$this</span>->level=<span>$_POST</span>['level'<span>]; </span><span>$this</span>->misses=0<span>; </span><span>$this</span>->setPageState('guessed',<span>null</span><span>); </span><span>//</span><span> show the guess page</span> <span>$this</span>->render('guess'<span>); } </span><span>else</span><span> { </span><span>$params</span>=<span>array</span><span>( </span>'levels'=><span>$levels</span>, <span>//</span><span> if this is a POST request, it means the level is not chosen</span> 'error'=>Yii::app()->request->isPostRequest,<span> ); </span><span>//</span><span> show the difficulty level page</span> <span>$this</span>->render('play',<span>$params</span><span>); } }</span>
<span>显然走的是else的逻辑,重点请看</span> $this->render('play',$params); 这个render方法这么面熟,很多框架中都有类似的方法,比如discuz,smarty,CI 等等. 纵观yii框架,rnder 在它整个MVC模式中,是V得以实现的重要骨干。所以有必要把它翻个底朝天。<br>在CController.php中有这个方法:
<span>public</span> <span>function</span> render(<span>$view</span>,<span>$data</span>=<span>null</span>,<span>$return</span>=<span>false</span><span>) { </span><span>if</span>(<span>$this</span>->beforeRender(<span>$view</span><span>)) { </span><span>$output</span>=<span>$this</span>->renderPartial(<span>$view</span>,<span>$data</span>,<span>true</span><span>); </span><span>if</span>((<span>$layoutFile</span>=<span>$this</span>->getLayoutFile(<span>$this</span>->layout))!==<span>false</span><span>) </span><span>$output</span>=<span>$this</span>->renderFile(<span>$layoutFile</span>,<span>array</span>('content'=><span>$output</span>),<span>true</span><span>); </span><span>$this</span>->afterRender(<span>$view</span>,<span>$output</span><span>); </span><span>$output</span>=<span>$this</span>->processOutput(<span>$output</span><span>); </span><span>if</span>(<span>$return</span><span>) </span><span>return</span> <span>$output</span><span>; </span><span>else</span> <span>echo</span> <span>$output</span><span>; } }</span>Wenn wir $output=$this->renderPartial($view,$data,true); ausgeben, stellen wir fest, dass $output zu diesem Zeitpunkt bereits unser Endergebnis erhalten hat. Die entsprechende Datei ist view/game/play.php
Das sehen wir endlich auf index.php. Da dieses Rendering relativ einfach ist, durchläuft das Programm weniger Prozesse, aber wie Sie dem Quellcode entnehmen können, wurden viele Verarbeitungsschritte durchgeführt, beispielsweise Themen usw. Dieses Mal werden wir dies zuerst analysieren. Gute Nacht!
Das Obige stellt die Quellcode-Analyse von YII (2) vor, einschließlich Aspekten des Inhalts. Ich hoffe, dass es für Freunde hilfreich sein wird, die sich für PHP-Tutorials interessieren.
<br>