I have a class named User that calls one of its own methods, setUsername(), upon construction, within a try/catch block. If setUsername() fails, it will throw an exception:
class User {
private $username;
public function __construct($input_username) {
try {
$this->setUsername($input_username);
} catch(Exception $e) {
throw $e;
}
}
private function setUsername($username) {
if(1 != 0)
throw new Exception("1 does not equal 0!!!");
$this->username = $username;
}
}
I then create a new User in an external function, in a separate file, within its own try/catch block. It's supposed to catch the exception passed through from the User class constructor:
namespace UserController;
function createUser(){
try {
$user = new \User('sample-user');
} catch(Exception $e) {
echo $e->getMessage();
}
}
Why, then, am I still getting an "Uncaught Exception" error?
It seems I was missing a statement at the top of the file that instantiates the class, since it is namespaced. After the namespace declaration, it needs to say:
use \Exception;
Related
I am using laravel 5.4. I have a method in a class that gets a new instance of a model class. The class's full name is computed at run time, so there is a chance the computed class name does not exists. In the case the class does not exists, I want to ignore any exception and I want to return null instead.
But, when an exception takes place, Laravel still throw the exception below even thought I believe it should not
[Symfony\Component\Debug\Exception\FatalThrowableError]
Class 'App\Models\CreatedBy' not found
Note that the string App\Models\CreatedBy was computed at run-time.
Here is my code
private function getForeignModelInstance()
{
try {
if (!$this->foreignModel) {
$model = $this->getFullForeignModel();
if ($model) {
$this->foreignModel = new $model();
}
}
return $this->foreignModel;
} catch (\Exception $e) {
return null;
}
}
How can ignore any error thrown and settle by returning null?
I think the best way is to prevent exception happen instead of hiding it. So before make a new class instance, check if its exists:
private function getForeignModelInstance()
{
try {
if (!$this->foreignModel) {
$model = $this->getFullForeignModel();
if ($model && class_exists($model)) {
$this->foreignModel = new $model();
}
return null;
}
return $this->foreignModel;
} catch (\Exception $e) {
return null;
}
}
Note: class_exists will not work using the short, aliased class name.
I'm trying to catch an error from my JWT class but i can't do it inside the class, the only place i can get it is from my main caller.
I'm calling this class with the error from my "API" where i start with the routing:
$router = new Router();
$router->all('/users', function()
{
$controller = new Controllers\UserController();
$controller->start();
});
$router->run();
After that i have my controller that will call my "API" class:
class UserAPI extends BaseAPI
{
protected $user;
protected $apiBase = "user";
function __construct($request, $origin)
{
parent::__construct($request);
$this->user = new User();
}
protected function logout()
{
if( isset($this->request[$this->apiBase . 'Data']) )
{
return $this->usuario->login($this->request[$this->apiBase . 'Data']);
}
else
{
return Helpers::errorResponse("User data not informed", 200);
}
}
}
And finally i have the problem, the User class where i want to catch an error but it wont work:
class User extends SimpleModel
{
public function logout($userData)
{
try
{
//At this point i will get an error since the provided token is invalid on purpose
$jwt = JWT::decode($userData['token'], SECRET_KEY, ['HS512']);
}
//Wont hit here even for a miracle
catch (Exception $exception)
{
echo "Caught ExceptFoo\n";
echo "Message: {$exception->getMessage()}\n";
}
}
}
The only place i could catch this error was on the routing file, wich is my index.php file.
For the JWT class i'm using Firebase JWT.
Relative class names (like Exception in your example) are always rooted to the namespace you are within. If you don't define a namespace, \ is used. Consider:
<?php
namespace Foo;
use Vendor\Package\Bar;
try {
Bar::throwAnException();
} catch (Exception $ex) {
die((string)$ex);
}
Here we have two relative class paths: Bar and Exception. PHP resolves Bar via the use statement to the absolute class path \Vendor\Package\Bar. PHP doesn't have a use statement corresponding to Exception, so PHP assumes you mean \Foo\Exception.
Clearly this isn't your intent. Unfortunately, PHP is silent when this situation occurs. It's bitten me a few times.
I'm working on a exception logging script, I use set_exception_handler() to handle uncaught exception.
Inside my custom exception handler, I use get_defined_vars() but it only return an array with a exception object, every variables created before exception thrown were disappear
$testing_var = 'testtesttest';
try {
throw new Exception("Error Processing Request");
} catch (Exception $e) {
var_dump(get_defined_vars()); // this could get $testing_var
}
set_exception_handler('exception_handler');
function exception_handler(exception)
{
var_dump(get_defined_vars()); // no, it can't get $testing_var, exception object only
}
throw new Exception("Error Processing Request");
In the scope where you are calling get_defined_vars() the variable you are after is not defined, so of course it will not be returned. from the docs:
This function returns a multidimensional array containing a list of all defined variables, be them environment, server or user-defined variables, within the scope that get_defined_vars() is called.
What are you trying to achieve? In general you should pass all information needed to handle the exception to the exception when constructing it. possibly using a custom exception class:
<?php
// custom exception class
// could be extended with constructor accepting an optional context
class ContextAwareException extends Exception
{
private $context;
public function setContext($context)
{
$this->context = $context;
}
public function getContext()
{
return $this->context;
}
}
function exception_handler($exception)
{
if ($exception instanceof ContextAwareException) {
$exception->getContext();
} else {
// we have no context
}
}
/*
* using this exception
*/
$testing_var = 'testtesttest';
$exception = new ContextAwareException("Error Processing Request");
$exception->setContext(get_defined_vars());
throw $exception;
I have found an alternate way to do this. I'm also looking for exception solution but this one works for me. If you use errors instead of exceptions - it seems to work.
set_error_handler('test','handler');
class test {
public static function handler($code, $error, $file = NULL, $line = NULL) {
throw new Exception($error, $code, 0, $file, $line);
return true;
}
}
$testVar='carolines';
try {
trigger_error('megamsg');
}
catch(Exception $e) {
var_dump($e);
$vars=$E BLABLABLA
}
Find yourself how to extract from $e. But if you debug You will see in trace handler function call with $testVar variable
I'm relatively new to PHP, I'm trying to make a script to log errors from try/catch blocks. I've run into a scope problem trying to do so.
First, I attempted to make the class instance a global variable but that didn't work.
I know it is possible to make a new instance each time 'AnotherClass' is called; however, that would clear the '$errors' array in 'errorhandler'.
I've been stuck on this issue for a few hours and any help would be greatly appreciated!
<?php
class errorhandler
{
private $errors = [];
function log($e = '')
{
print "Opps! An error occured: " . $e;
array_push($this->errors, $e);
}
}
# global $errorhandler; # Doesn't work...
$errorhandler = new errorhandler();
class AnotherClass
{
function __construct()
{
try {
$not_possible = 1/0;
} catch (Exception $e) {
$errorhandler->log($e); # Doesn't work
}
}
}
new AnotherClass();
?>
Thanks :)
You have to import the global $errorhandler variable into your local scope:
class AnotherClass
{
function __construct()
{
global $errorhandler;
try {
$not_possible = 1/0;
} catch (Exception $e) {
$errorhandler->log($e); # Doesn't work
}
}
}
P.S. 1/0 is not an exception, it's a runtime error. You can't catch those with a try/catch block.
In the following example, if the class does not exist, I want to catch the error and create a Null class instead.
But in spite of my try/catch statements, PHP simply tells me Class 'SmartFormasdfasdf' not found.
How can I get PHP to catch the 'class not found' error?
<?php
class SmartFormLogin extends SmartForm {
public function render() {
echo '<p>this is the login form</p>';
}
}
class SmartFormCodeWrapper extends SmartForm {
public function render() {
echo '<p>this is the code wrapper form</p>';
}
}
class SmartFormNull extends SmartForm {
public function render() {
echo '<p>the form "' . htmlentities($this->idCode) . '" does not exist</p>';
}
}
class SmartForm {
protected $idCode;
public function __construct($idCode) {
$this->idCode = $idCode;
}
public static function create($smartFormIdCode) {
$className = 'SmartForm' . $smartFormIdCode;
try {
return new $className($smartFormIdCode);
} catch (Exception $ex) {
return new SmartFormNull($smartformIdCode);
}
}
}
$formLogin = SmartForm::create('Login');
$formLogin->render();
$formLogin = SmartForm::create('CodeWrapper');
$formLogin->render();
$formLogin = SmartForm::create('asdfasdf');
$formLogin->render();
?>
Solution:
Thanks #Mchl, this is how I solved it then:
public static function create($smartFormIdCode) {
$className = 'SmartForm' . $smartFormIdCode;
if(class_exists($className)) {
return new $className($smartFormIdCode);
} else {
return new SmartFormNull($smartFormIdCode);
}
}
Because it's a fatal error. Use class_exists() function to check if class exist.
Also: PHP is not Java - unless you redefined default error handler, it will raise errors and not throw exceptions.
Old question, but in PHP7 this is a catchable exception. Though I still think the class_exists($class) is a more explicit way to do it. However, you could do a try/catch block using the new \Throwable exception type:
$className = 'SmartForm' . $smartFormIdCode;
try {
return new $className($smartFormIdCode);
} catch (\Throwable $ex) {
return new SmartFormNull($smartformIdCode);
}
php >= 7.0
php can catch 'class not found' as Throwable
try {
return new $className($smartFormIdCode);
} catch (\Throwable $ex) {
return new SmartFormNull($smartformIdCode);
}
You need to use class_exists to see if the class exists before you try and instantiate it.
Incidentally, if you're using a class autoloader, be sure to set the second arg to true.
Because php emits fatal error when you ty to create new object of non existing class. To make it work you will need php >= 5.3 and autoload function, where you should try to look for file with class definition or throw your custom exception.