Yii-Shell funktioniert nach Erzeugen einer eigenen CWebApplication-Klasse nicht mehr

Hallo zusammen,

und zwar beschreibe ich zunächst mal den Stand, wie ich ihn im Moment habe. Danach komme ich auf mein Problem zu sprechen.

Ich habe mir eine eigene Instanz von CWebApplication erzeugt und wie folgt alles gespeichert:

  • index.php

<?php


// Umleitung auf die passende Domain, aber nur, wenn es keine lokaler Seiten-

// aufruf ist.

if ($_SERVER['SERVER_NAME'] != 'localhost')

{

	$domain = 'www.internationale-giuseppe-verdi-stiftung.org';

	if (strtolower($_SERVER['SERVER_NAME']) != $domain)

	{

		header("HTTP/1.1 301 Moved Permanently");

		header("Location: http://" . $domain . $_SERVER['REQUEST_URI']);

	}


}


// -----------------------------------------------------------------------------

// remove the following line when in production mode

//defined('YII_DEBUG') or define('YII_DEBUG',true);


// Diese Zeile entkommentieren, um den Wartungsmodus zu aktivieren

//define('MAINTAINING_SYSTEM', true);


// -----------------------------------------------------------------------------




// Prüfen, ob der Wartungsmodus aktiv ist

if (defined('MAINTAINING_SYSTEM'))

{

	// WArtungsmodus anzeigen

	require('maintenance.php');

}

else

{

	// change the following paths if necessary

	$yii	= dirname(__FILE__).'/protected/yii.php';

	$config	= dirname(__FILE__).'/protected/config/main.php';


	require_once($yii);

	Yii::createWebApplication($config)->run();

}


?>

  • protected\MyWebApplication.php

<?php


class MyWebApplication extends CWebApplication

{

	/**

	 * Konstruktor.

	 **/

	public function __construct($config=null) {

		parent::__construct($config);

	}


	/**

	 * Diese Methode stellt fest, ob der User einen Internet Explorer 6.0 oder

	 * kleiner verwendet.

	 **/

	public function isIE6OrSmaller()

	{

		if( eregi("(msie) ([0-9]{1,2}.[0-9]{1,3})", $_SERVER['HTTP_USER_AGENT'], $regs) )

		{

			// Es ist ein IE; Prüfung, ob die Version kleiner als 7 ist, denn

			// dann muss die Funktion true zurück liefern

			return ($regs[2] < 7);

		}

		else

		{

			// Es ist ein anderer Browser als der IE

			return false;

		}

	}

}


?>

  • protected\MyYiiBase.php

<?php


require('./yii/YiiBase.php');

require('./protected/MyWebApplication.php');


class MyYiiBase extends YiiBase

{

	/**

	 * Die Standardmethode zum Erzeugen der Web-Application überschreiben,

	 * sodass keine CWebApplication erzeugt wird, sondern MyWebApplication.

	 **/

	public static function createWebApplication($config=null)

	{

		return new MyWebApplication($config);

	}

}


?>

Nun wollte ich die Yii-Shell starten, sodass ich einige Controller und Models automatisch anlegen kann. Hier das Ergebnis:


D:\xampp\htdocs\project>protected\yiic shell


Fatal error: Cannot redeclare class YiiBase in D:\xampp\htdocs\project\yii\

YiiBase.php on line 53


D:\xampp\htdocs\project>

Ich habe keinerlei Ahnung, wie der Fehler zustande kommt. Mir ist klar, dass PHP diesen Fehler wirft und dieser nicht direkt aus Yii kommt. Kennt jemand von euch diesen Fehler?

hab das problem weiter eingrenzen können. es liegt daran, dass zwei mal die YiiBase.php eingebunden wird. muss mir das noch was einfallen lassen, wie ich das löse… melde mich dann wieder!

so, nun habe ich alles nötige gefixt und umgeschrieben, sodass es nun passt! und zwar musste ich die folgenden dateien ändern (achtet auf die kommentare!). an dieser stelle muss ich darauf hinweisen, dass mein framework nicht im ordner "framework" liegt, sondern im ordner "yii":

  • protected/yiic.php

<?php

// -----------------------------------------------------------------------------------

// THESE TWO LINES WHERE ADDED

defined('YII_OWN_APPLICATION_CLASS') or define('YII_OWN_APPLICATION_CLASS',true);

require_once(dirname(__FILE__).'/yii.php');

// -----------------------------------------------------------------------------------


// change the following paths if necessary

$yiic=dirname(__FILE__).'/../yii/yiic.php';

$config=dirname(__FILE__).'/config/console.php';


require_once($yiic);


?>

  • yii/yiic.php

<?php

/**

 * Yii command line script file.

 *

 * This script is meant to be run on command line to execute

 * one of the pre-defined console commands.

 *

 * @author Qiang Xue <qiang.xue@gmail.com>

 * @link http://www.yiiframework.com/

 * @copyright Copyright &copy; 2008-2009 Yii Software LLC

 * @license http://www.yiiframework.com/license/

 * @version $Id: yiic.php 1211 2009-07-05 04:54:10Z qiang.xue $

 */


// fix for fcgi

defined('STDIN') or define('STDIN', fopen('php://stdin', 'r'));


defined('YII_DEBUG') or define('YII_DEBUG',true);

error_reporting(E_ALL ^ E_NOTICE);


// -----------------------------------------------------------------------------------

// HERE COMES THE LINE!!!

if (!defined('YII_OWN_APPLICATION_CLASS')) require_once(dirname(__FILE__).'/yii.php');

// BEFORE:

//require_once(dirname(__FILE__).'/yii.php');

// -----------------------------------------------------------------------------------


if(isset($config))

{

	$app=Yii::createConsoleApplication($config);

	$app->commandRunner->addCommands(YII_PATH.'/cli/commands');

}

else

	$app=Yii::createConsoleApplication(array('basePath'=>dirname(__FILE__).'/cli'));


$app->run();



Sollte sich require_once nicht schon allein drum kümmern, dass die yii.php nicht zweimal eingebunden wird? Nach meinem Verständnis sollte das define völlig überflüssig sein.

Oh, und sollte in der index.php nicht folgendes stehen?




//Yii::createWebApplication($config)->run();

MyYiiBase::createWebApplication($config)->run();



Das Problem mit der Fehlermeldung ist bekannt. Es liegt daran, dass yiic shell die index.php einbindet (also eigentlich die Startseite deiner Webapp aufruft), deren Ausgabe aber per Output-Buffering abfängt. So versucht die Yiic-Shell möglichst intelligent an die Konfiguration der Webapp ranzukommen. Ich weiß nicht mehr genau, warum dieses Problem nicht immer auftrat. Aber man kann es umgehen, indem man den Pfad zur Konfigdatei übergibt:

yiic shell ./protected/config/main.php

Und wenn ich noch etwas klugsch… darf ;)

Dein Konstruktor in MyWebApplication ist nicht nötig. Außerdem würd ich die Funktion isIE6OrSmaller() logisch eher in eine Klasse MyHttpRequest (extends CHttpRequest) packen. Diese kannst du dann in der main.php als request component definieren.

Muss aber auch nicht sein ;)

Hey,

ich habe das ganze nun etwas anders gelöst, aber danke für deinen Hinweis! Ich muss das mal testen, was du hier geschrieben hast.

Der Konstruktor ist hier nur noch ein “Überbleibsel” von einer Copy and Paste-Aktion, da ich diesen in einem anderen Projekt benötigt hatte ;) Trotzdem vielen Dank für den Hinweis.

Zum Thema MyHttpRequest: und zwar habe ich eine eigene Klasse MyWebApplication geschrieben um global an Funktionen zu gelangen, u.a. aber auch um wichtige Parameter dort zwischenspeichern und von überall aufrufen zu können. Daher habe ich auch nicht nur diese Methode dort enthalten. Wie genau würde das mit einem CHttpRequest laufen?

Ist sicher nicht verkehrt, das in MyWebApplication zu legen. Viele verwenden auch das "BaseController"-Konzept für solche Sachen. Also eine Klasse BaseController extends CController von der dann deine Controller abgeleitet werden. In den Basecontroller kann man dann allerhand Sachen packen, die man überall braucht.

Da ich bei OOP allerdings immer versuche, die Sachen da hinzupacken, wo sie logisch hingehören, würd ich diese IE-Testfunktion eben in das Request-Objekt mit reinpacken, dass von Yii ja ohnehin erstellt wird:


class MyRequest extends CHttpRequest {


   public function getIsIE6OrSmaller() {

      // ...

   }

}



In der main.php:


'components' =>array(

   //...

   'request' => array('class'=>'MyRequest'),

   // ...



Übrigens hab ich dank Dave gesehen, dass es in CHttpRequest (Abrufbar über Yii::app()->request) ohnehin schon die Eigenschaft browser gibt. Es würde sich also in der getIsIE6OrSmaller() anbieten, sich das mit $this->browser zu holen und zu analysieren.

All das sind aber wiegesagt schon auch Geschmacksfragen. Jeder entwickelt ja so seinen eigenen Programmierstil.

Ja, dessen bin ich mir auch sicher. Aber wenn man was besser machen kann – und das ist es in diesem Fall u.U. durchaus – dann kann man seinen Stil ja dementsprechend optimieren! Danke für den Hinweise, ich werde das mal verinnerlichen. Es gibt halt leider so viele kleine Stellen, an denen meine IDE mir nicht weiterhilft, sodass ich eben selbst Lösungen bastle, wofür es aber schon welche gibt.