Problem mit $this ...

Hallo,
ich weiß echt nicht warum aber wenn ich einen Fehler mit getSettings provozieren will dann bekomme ich "Fatal error: Using $this when not in object context in C:\xampp\htdocs\www\9mango\core\classes\Core.php on line 60" langsam kenne ich mich nicht mehr aus…

ich hoffe ihr könnt mir helfen

Db.php

[CODE]
//Namespace
namespace core\classes;

use core\classes\exceptions\DatabaseErrorHandler as DatabaseErrorHandler;

//Class
class Db extends \MySQLi {

/* Constructor */ 
public function __construct() {
     $this->connect();
}


/* Datenbankverbindung */ 
public function connect()
{   
    try 
    {
        @parent::connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
        
        if (mysqli_connect_errno()){
            throw new DatabaseErrorHandler(mysqli_connect_error(), mysqli_connect_errno());        
        }
           
    } 
    catch (DatabaseErrorHandler $e) 
    {
        $e->_buildErrorPage();
        
    }  
}[/CODE]Core.php 

[CODE]
/* Benötigte Klassen werden instanziert */
private function loadClasses() {

    $this->_db = Registry::get("db");
    
}


/* SETTINGS LADEN  */
public function getSettings($name, $typ) {
    // Query vorbereiten und an die DB schicken
    try {
        $sql = "SELECT * FROM ".DB_PRÄFIX."settings WHERE name='$name' and typ='$typ'";
       [B] $result = $this->_db->query($sql); // ich bin Zeile 60[/B]
        if($result) {
            while($row = $result->fetch_object()) 
            {
                return $row->value;   
            } 
        } else {
            throw new SystemErrorHandler("Die gesuchte Einstellung wurde nicht gefunden", 1);        
        }
    }
    catch (DatabaseErrorHandler $e) {
        $e->_buildErrorPage();    
    }
    catch (SystemErrorHandler $e) {
        $e->_buildErrorPage();
    }   
    $result->_db->close();
}
[/CODE]mfg

$this bereitet immer Probleme, weil this (ohne $) gibt es ja auch ;D einfach $this in $that ändern und es müsste funktionieren (jedenfalls tuts das bei mir immer xD)

Timmäh =)

Mag sein, dass sich das Problem aus dem gezeigten Code irgendwie erkennen ließe, aber ich frage trotzdem lieber: Welche Zeile ist denn Zeile 60?

$result = $this->_db->query($sql); // ich bin Zeile 60
: ) ich werde sie noch bissl besser markieren(geht das überhaupt innerhalb eines code tags in vb? xD)

einfach $this in $that ändern und es müsste funktionieren

Funktioniert bei mir nicht danke trotzdem^^

Rufst du getSettings vielleicht statisch (Klasse::getSettings) auf?

Für mich sieht der gezeigte Code okay aus (oder er würde glaube ich zumindest nicht die beschriebene Fehlermeldung liefern). Ich fürchte, da bräuchte man für eine Antwort im Zweifel mehr Kontext.

Lass dir Objekte/Variablen an geeigneten Stellen per var_dump() ausgeben. Dann kommst du vielleicht auf die Spur, welcher Code wo nicht mehr erreicht wird oder welche Variable wann welchen Wert hat, obwohl sie eigentlich einen anderen haben sollte.

oh im test ruf ich es eigentlich statisch auf^^

…gerade geändert wobei jetzt „Notice: Undefined property: mysqli_result::$_db“ kommt

so ich habe jetzt den Fehler wegbekommen : )

jetzt habe ich nur noch das Problem mit der nicht ausgegebenen Exception : (

[CODE]/* SETTINGS LADEN */
public function getSettings($name, $typ) {
// Query vorbereiten und an die DB schicken
try {
$sql = "SELECT * FROM ".DB_PRÄFIX.„settings WHERE name=‚$name‘ and typ=‚$typ‘“;
$result = $this->_db->query($sql);

        if($result) {
            while($row = $result->fetch_object()) 
            {
                return $row->value;   
            } 
        } else {
            throw new SystemErrorHandler("Die gesuchte Einstellung wurde nicht gefunden", 1);        
        }
    }
    catch (DatabaseErrorHandler $e) {
        $e->_buildErrorPage();    
    }
    catch (SystemErrorHandler $e) {
        $e->_buildErrorPage();
    } 
}[/CODE]

Du machst das ein bisschen kompliziert. Die Idee wäre, zentral einen Error Handler zu definieren, der alle Exceptions bearbeitet, die nicht vorher gefangen wurden.

Das heißt, du kannst einfach fangen, was du fangen willst, und alle anderen Fehler stumpf ignorieren für den Standard-Handler.

[php]<?php

class ErrorController
{
public function errorAction($exception)
{
echo ‚

„We encountered an error, sir!“

‘;
echo ‚

„Put it on screen, Number One.“

‘;
echo ‚
‘ . $exception . ‚
‘;
}
}

error_reporting(-1);

$err = new ErrorController();

set_exception_handler(array($err, ‚errorAction‘));
set_error_handler(
function ($errno, $errstr, $errfile, $errline, array $errcontext = null)
{
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
});

try {
throw new Exception(‚Gonna catch this‘);
} catch (Exception $e) {
// Error? What error? I can see no error. You are lying.
}

Test 1 (comment the following line to enable Test 2)

throw new Exception(‚Ooops!‘);

Test 2

$i = 3;
echo $i / 0;[/php]

Danke für deine Hilfe

Was genau meinst du mit Zentral und wo sollte dieser dann zum Einsatz kommen(bzw. das try and catch) ?

Du willst ja offensichtlich in manchen Fällen eine eigene Fehlerseite erzeugen ($e->_buildErrorPage();). Den wiederkehrenden Aufruf der entsprechenden Funktion kannst du dir sparen, indem du einmal eine Methode angibst, die alle nicht bearbeiteten (= gefangenen) Fehler behandelt. Du würdest in deiner getSettings-Methode zum Beispiel den try-catch-Block weglassen und die Ausführung käme dennoch automatisch bei ErrorController::errorAction an, weil die Exceptions vorher nicht gefangen werden.

Achso, wenn ich den set Exception Handler setze sollte dies Global z.B. in der Bootstrap oder in der jeweiligen Datei geschehen? Wenn ja sollte dies dann so eine Art Top Level Handler sein der z.B. nicht gefangene Exceptions „aufnimmt“? Soll ich auf Try and Catch ganz verzichten? Gibt es für diese Methode irgendwelche Nachteile?

Achso, wenn ich den set Exception Handler setze sollte dies Global z.B. in der Bootstrap oder in der jeweiligen Datei geschehen?

Ja, genau. Bootstrap.

Wenn ja sollte dies dann so eine Art Top Level Handler sein der z.B. nicht gefangene Exceptions „aufnimmt“?

…und aus der Exception dann eine Fehlerseite generiert wie eine ganz normale Action eine normale Seite generiert. Es war mein Eindruck, dass du genau sowas machen wolltest mit $e->_buildErrorPage().

Soll ich auf Try and Catch ganz verzichten? Gibt es für diese Methode irgendwelche Nachteile?

Abfangbare Fehler, die nicht zum Abbruch der Ausführung des Scripts führen müssen (bzw. nicht zur Ausgabe einer Fehlerseite), kannst und solltest du auch weiterhin mit try-catch behandeln.

Edit: Der globale Error/Exception Handler ist einfach eine mit weniger Redundanz und Logikcode verbundene Art und Weise, die Fehlerseiten-Funktionalität umzusetzen.

Jetzt hab ich die Klasse etwas geändert,… ich musste den __constructor in set_exception_handler angeben ansonsten würde es ja nicht parent::construct aufrufen… nun weiß ich bald nicht mehr ob das so elegant genug bzw. eine gute Lösung ist, vl kannst mir ja (wiedereinmal) helfen

Ausschnitt aus Bootstrap:

[CODE]use core\classes\exceptions\SystemErrorHandler as SystemErrorHandler;

$la = new SystemErrorHandler();

set_exception_handler(array($la, ‚__construct‘));[/CODE]

SystemExceptionHandler

[CODE]namespace core\classes\exceptions;

use core\classes\exceptions\View as View;

//Class
class SystemErrorHandler extends \Exception {

public function __construct($ErrorMessage = null, $ErrorCode = 0){

 parent::__construct($ErrorMessage, $ErrorCode);

}

public function _buildErrorPage(){

 $page = new View();
 $page->setView("SystemErrorHandler"); 
 $page->assign('message',$this->getMessage());
 $page->assign('code',$this->getCode());
 $page->assign('file',$this->getFile());
 $page->assign('line',$this->getLine());
 $page->assign('trace',$this->getTraceAsString());
 
 $page->parseView();

}[/CODE]

zudem muss ich doch auch so immer den vollen Namespace Pfad des SystemErrorHandler in den Klassen angeben…

Der „Fehler“ ist, SystemErrorHandler von Exception abzuleiten. Das ergibt inhaltlich auch keinen Sinn.

Ich habe noch mal versucht, das Beispiel für deine Klassen umzuschreiben, vielleicht ist das offensichtlicher.

[php]<?php

class SystemErrorHandler
{
public function _buildErrorPage(Exception $exception)
{
$page = new View();
$page->setView(„SystemErrorHandler“);
$page->assign(‚message‘,$exception->getMessage());
$page->assign(‚code‘,$exception->getCode());
$page->assign(‚file‘,$exception->getFile());
$page->assign(‚line‘,$exception->getLine());
$page->assign(‚trace‘,$exception->getTraceAsString());

    $page->parseView();
}

}

class DatabaseException extends Exception{}
class SystemException extends Exception{}

class View
{
protected $data = array();
public function setView($script){}
public function assign($key, $value){$this->data[$key]=$value;}
public function parseView()
{
echo ‚

Debug

‘;
print_r($this->data);
}
}

class Foo
{
/* SETTINGS LADEN */
public function getSettings($name, $typ) {
// Query vorbereiten und an die DB schicken

    //$sql = "SELECT * FROM ".DB_PRÄFIX."settings WHERE name='$name' and typ='$typ'";
    //$result = $this->_db->query($sql);

    $result = false;

    if($result) {
        while($row = $result->fetch_object())
        {
            return $row->value;
        }
    } else {
        throw new SystemException("Die gesuchte Einstellung wurde nicht gefunden", 1);
    }
}

}

// Bootstrap

$la = new SystemErrorHandler();

set_exception_handler(array($la, ‚_buildErrorPage‘));

// Test

$foo = new Foo();
$foo->getSettings(‚foo‘, ‚bar‘);[/php]

Zunächst möchte ich dir mal danken, dass du mir hilfst^^

Nun ich habe das jetzt so umgesetzt wie du es mir erklärt hast jedoch gibt mir PHP einen Fehler aus

Catchable fatal error: Argument 1 passed to core\classes\errorhandler\SystemErrorHandler::_buildErrorPage() must be an instance of core\classes\errorhandler\Exception, instance of core\classes\exceptions\SystemException given in C:\xampp\htdocs\www\9mango\core\classes\errorhandler\SystemErrorHandler.php on line 21

Exception meint in meinem Beispiel immer \Exception.

Eine Methodensignatur wie…

    public function _buildErrorPage(Exception $exception) 

…nimmt als Parameter dann jedes Objekt entgegen, das eine \Exception ist oder das von \Exception abgeleitet ist. (Die Namespace-Slashes müsstest du unter Umständen eben ergänzen.) Ganz normaler Umgang mit Vererbung.

Eigene Exceptions sollten dann logischerweise von \Exception abgeleitet werden (siehe mein Beispiel).

thx habs jetzt kapiert… : )

nun alles funktioniert soweit bis auf, dass wenn nichts gefunden wurde keine Exception geworfen wird…

[CODE] /* SETTINGS LADEN */
public function getSettings($name, $typ) {
// Query vorbereiten und an die DB schicken
$sql = "SELECT * FROM ".DB_PRÄFIX.„settings WHERE name=‚$name‘ and typ=‚$typ‘“;
$result = $this->_db->query($sql);

    if($result == true) {
        while($row = $result->fetch_object()) 
        {
            return $row->value;   
        } 
    } else {
        throw new SystemException("Die gesuchte Einstellung wurde nicht gefunden", 1);        
    }
}

[/CODE]

push Hat jemand ne ahnung woran es liegt?

Ach so, ich hatte das nicht mehr als Frage interpretiert. $result ist ein mysqli_result?

Ungetestet:

[php]if ($result->num_rows === 0) {
throw new Exception(‚Empty query result‘);
}[/php]

Ach so, ich hatte das nicht mehr als Frage interpretiert

kein Ding, es war eher so eine indirekte Frage xD

$result ist ein mysqli_result?

Also gibt mir Mysqli query wenn nichts gefunden wurde kein False back?