try..catch verschachtelt

kevkev

Erfahrenes Mitglied
Hi,

Ich habe da eine verschachtelte try..catch Abfrage:
PHP:
try {
 do something
       try {
        do something
       } catch () {
        catchit
       }
} catch () {
 catchit
}

Das Problem ist, dass das zweite try..catch immer durchläuft, obwohl direkt darüber bereits durch die erste try..catch eine Exception erzeugt worden ist.

Wie kann ich das lösen, dass das zweite try..catch nur durchläuft, wenn davor noch keine Exception geworfen worden ist?

In der ersten überprüfe ich z.b. ob eine Datei vorhanden ist, in der zweiten try..catch ob die Datei gültig ist, und in der dritten ob die Dateigröße stimmt (als beispiel).
Wenn nämlich bereits in der ersten der Fehler gefunden wird, brauchen/dürfen die nächsten try..catches nicht durchlaufen, da diese in jedem Fall eine weitere unnötige Exception werfen würde.

Danke!

Gruß
Kevin
 
Zuletzt bearbeitet:
In deinem Beispiel läuft die zweite try..catch auch durch, wenn davor irgendwo eine Exception geworden worden ist, oder?

Mein Problem ist, das ich viele Methoden von verschiedenen Klassen in einem durchlauf nutze, jedoch sollen andere Methoden nicht ausgeführt werden, wenn bereits irgendwo eine Exception aufgetreten ist.
 
Zuletzt bearbeitet:
Das Problem ist, dass das zweite try..catch immer durchläuft, obwohl direkt darüber bereits durch die erste try..catch eine Exception erzeugt worden ist.

Was gefangen wird, wird gefangen, und nicht grundlos weitergereicht. Einzige Ausnahme bilden diese Fälle:
PHP:
try {
    try {
        // ...
    } catch ( Exception $e ) {
        throw $e;
    } catch ( Exception2 $e ) {
        throw new Exception();
    }
    // ...
} catch ( Exception $e ) {
    // ...
}

// oder

try {
    try {
        // ...
    } catch ( Exception $e ) {
        // ...
    }
    // ...
    throw new Exception();
    // ...
} catch ( Exception $e ) {
    // ...
}

Wie kann ich das lösen, dass das zweite try..catch nur durchläuft, wenn davor noch keine Exception geworfen worden ist?
In der ersten überprüfe ich z.b. ob eine Datei vorhanden ist, in der zweiten try..catch ob die Datei gültig ist, und in der dritten ob die Dateigröße stimmt (als beispiel).
Wenn nämlich bereits in der ersten der Fehler gefunden wird, brauchen/dürfen die nächsten try..catches nicht durchlaufen, da diese in jedem Fall eine weitere unnötige Exception werfen würde.

Ein eher den gewöhnlichen Ansätzen entsprechender Versuch könnte so aussehen:
PHP:
try {
    if ( !fileExists() ) { throw new BadFileException(); }
    if ( !isValidFile() ) { throw new InvalidFileException(); }
    if ( !hasValidSize() ) { throw new InvalidFileSizeException(); }
    // ...
} catch ( BadFileException $e ) {
    // ...
} catch ( InvalidFileException $e ) {
    // ...
} catch ( InvalidFileSizeException $e ) {
    // ...
}
 
Hier mal ein Beispiel:
PHP:
 try{
	throw new Exception('Exception 1');
	
	echo "wird nie ausgegeben";
	
	try{
		throw new Exception("Exception 2");
	}catch(Exception $e){
		echo "verschachtelte Exception";
		print_r($e);
	}
	
	echo "wird auch nie ausgegeben";
}catch(Exception $e){
	print_r($e);
}

echo "wird immer ausgegeben";
 
Warum überhaupt verschachteln?

Du könntest alle drei Exceptions am selben Punkt auffangen und dann der Meldung entsprechend handeln.

PHP:
try
{
// Datei prüfen

// Datei validieren

// Dateigröße
}
catch()

Du könntest z. B. mit Konstanten arbeiten oder mit einer eigenen Exceptionsklasse.

Die andere Alternative wäre einfach, dass du verschiedene Exceptionsklassen benutzt. Dementsprechend würde catch nur greifen, wenn es die richtige Exceptionklasse versucht aufzufangen.
 
Danke für die vielen Antworten :-).

Ich möchte mein Beispiel ein wenig näher der eigentlichen Aufgabe bringen:

1. Datei auf Existenz überprüfen
2. Datei selbst prüfen (valid mimetype etc)
3. Dateioperationen anwenden
4. Datei mittels XMLRPC übertragen
5. Rückgabewerte abhandeln

Das ganze ist schwer zusammen zufassen, allein Schritt 3. hat eine eigene Klasse mit über 20 Methoden, die wiederrum jeweils verschiedene Exceptions werfen.

Die Lösung von maeTimmae, für jeden Fehler eine extra Exception zu werfen (FileNotFound, etc.) geht leider anhand der Größe aller möglichen Fehler nicht.


Ich glaub ich hab mein Problem gefunden :rolleyes::

Ich hatte ca. 10 verschachtelte try..catches in einer Methode und in jedem catch() hatte ich wieder eine Exception geworfen, was eigentlich für die Nutzung der Methode am Ende gedacht war.

So sind nun die Exceptions immer weiter nach oben gewandert, bis zum letzten try..catch, das dann schlussendlich ausgegeben worden ist. :suspekt:.

Ich glaube ich bin mit einer Überprüfung der jeweiligen Schritte mit einfachen if-Abfragen einfacher und sinnvoller getan.
So kann ich jedenfalls auch Exceptions bis hoch zur letzten Nutzung durchlaufen lassen.


Also so machte ich das bisher:
PHP:
public function test () {
	try {
		/** check file exists */
		echo "check file exists<br />";

		try {
			/** check file is okay */
			echo "check file is okay<br />";

			try {
				/** transfer file */
				echo "transfer file<br />";
				
				/** dieses throw loest nun die filetransferfailed, filenotokay und die filenotfound exception aus */
				throw new Exception("somethingwrongwithfiletransfer");
			

			} catch(Exception $e) {
				throw new Exception("filetransferfailed");
			}

		} catch(Exception $e) {
				throw new Exception("filenotokay");
		}

	} catch(Exception $e) {
		throw new Exception("filenotfound");
	}
}

Wäre diese Lösung hier "besser"?
PHP:
public function test () {
	
	if (checkfileexists()) {
		//... do
		
		if (checkfileisokay()) {
			//... do
			
			if (transferfile()) {
				//... do
				
			} else {
				throw new Exception("filetransferfailed");
			}
		} else {
			throw new Exception("filenotokay");
		}
	} else {
		throw new Exception("filenotfound");
	}
}

Oder sollte ich die Exceptions bereits bei der Überprüfung ("checkfileexists()", also von der Methode her direkt selber) thrown?

Danke!

Gruß
Kevin
 
Zuletzt bearbeitet:
Ich würd’s wie folgt machen:
PHP:
try {
	/** check file exists */
	if (!file_exists($file)) {
		throw new Exception("file does not exists");
	}
	if (!is_file($file)) {
		throw new Exception("file is not a regular file");
	}
	if (!is_readable($file)) {
		throw new Exception("file is not readable");
	}
	if (!($content = file_get_contents($file))) {
		throw new Exception("error while reading file");
	}
	// weitere Verarbeitung
} catch (Exception $e) {
	handleError($e);
}
Wobei einige Prüfungen in diesem Fall auch redundant sind.
 
Ich werde das aber viell. verschachteln, da manche Überprüfungen auch true ergeben, die z.b. im späterem Ablauf nichts mit Dateien mehr zu tun haben (z.b. Konnektivität eines Server feststellen).

Danke an alle :).

Edit:
Verschachteln ist natürlich Banane...
Die Lösung von Gumbo (wurde weiter oben auch mehrmals genannt) ist genau die Richtige, ich hatte vergessen(?) das bei einem throw der Programmablaufen abgebrochen wird, und daher auch die nachfolgenden überprüfungen nicht ausgeführt werden.

Nochmals großes Danke, komme nun endlich an meinem Projekt weiter..
 
Zuletzt bearbeitet:
Zurück