Try/catch VS fopen (to check valid file's URL) - php

Hi there I want to check error-handling for an external URL (film/images) to know it is valid or not.(in my server)
I Found 2 methods:
First: try-catch method
try {
$path = savePic(...);
}
catch (MalformedURLException e) {
// exception handler code here
// ...
}
Or something like this:
if($file = fopen ($url, "rb")
{
$path = savePic($file);
}
else
{
// URL is invalid
}
Which one is better and faster for a large file?
Is there a better method to do it?
}

Related

php try catch not working properly

I have code like this:
try {
$providerError = false;
$providerErrorMessage = null;
$nbg_xml_url = "http://www.somesite.com/rss.php";
$xml_content = file_get_contents($nbg_xml_url);
// ... some code stuff
} catch (Exception $e) {
$providerError = true;
$providerErrorMessage = $e -> getMessage();
$usd = 1;
$rate = null;
$gel = null;
} finally {
// .. Write in db
}`
and problem is that, when file_get_contents can not read url (may be site not responding or something like this..) my code writes error: failed to open stream: HTTP request failed! and execution goes direct to finally block bypass catch block without entering in it..
any ideas?
You can set an empty error handler to prevent the warning and afterward throw a custom exception in case of failure. In this case I would write a custom file_get_content like so:
function get_file_contents($url) {
$xml_content = file_get_contents($url);
if(!$xml_content) {
throw new Exception('file_get_contents failed');
}
return $xml_content;
}
and would use it in your block:
set_error_handler(function() { /* ignore errors */ });
try {
$providerError = false;
$providerErrorMessage = null;
$nbg_xml_url = "http://www.somesite.com/rss.php";
$xml_content = get_file_contents($nbg_xml_url); //<----------
// ... some code stuff
} catch (Exception $e) {
$providerError = true;
$providerErrorMessage = $e -> getMessage();
$usd = 1;
$rate = null;
$gel = null;
} finally {
// .. Write in db
}
Then remember to restore the error handler calling:
restore_error_handler();
Note that when using your own error handler it will bypass the
error_reporting
setting and all errors included notices, warnings, etc., will be passed to it.
$xml_content = file_get_contents($nbg_xml_url);
The function file_get_contents does not throw an exception. Thus an exception will not be thrown if as you say the file is not found.
From the docs:
An E_WARNING level error is generated if filename cannot be found...
This function returns the read data or FALSE on failure. So you could check if $xml_content is FALSE ($xml_content === false) and proceed accordingly.
This is a php code for catching any error or exception.
Throwable is the base interface for any object that can be thrown via a throw statement, including Error and Exception.
This will catch fatal errors too. Without throwable it will not catch fatal errors.
try {
// Code that may throw an Exception or Error.
} catch (Throwable $t) {
// Executed only in PHP 7, will not match in PHP 5.x
} catch (Exception $e) {
// Executed only in PHP 5.x, will not be reached in PHP 7
}

How to catch exceptions in entity?

I have a method in my entity with #ORM\PostRemove() which removes an associated file.
I wonder if I should do something like this:
try {
unlink($file);
} catch (\Exception $e) {
// Nothing here?
}
Does it make sense to catch an exception and do nothing in catch block? Or maybe I shouldn't catch exception here, but then, where should I do it? Should it be an exception from LifecycleCallback method?
I've read here that I shouldn't use logger in entity, so I'm confused what to put there instead.
Your entity shouldn't really contain business logic for your application, its purpose is to map objects to the database records.
The way to approach this depends on the application, for example if you have a File Controller and a removeAction within then the best place to remove the file would likely be here.
As an example: (psuedo code)
public function removeAction($id) {
$em = $this->getDoctrine()->getEntityManager();
$file = $em->getRepository('FileBundle:File')->find($id);
if (!$file) {
throw $this->createNotFoundException('No file found for id '.$id);
}
$filePath = $file->getPath();
if (file_exists($filePath) {
try {
unlink($filePath);
}
catch(Exception $e) {
// log it / email developers etc
}
}
$em->remove($file);
$em->flush();
}
You should always add error checking and reporting in your application, check that a file exists before you attempt to remove it.

Why not checking if template file really exists in ZF2?

In ZF 2.2.5 Zend\View\Renderer\PhpRenderer::render method there is an if statement that checks if template exists in template stack (line 497)
$this->__file = $this->resolver($this->__template);
if (!$this->__file) {
throw new Exception\RuntimeException(sprintf(
'%s: Unable to render template "%s"; resolver could not resolve to a file',
__METHOD__,
$this->__template
));
}
try {
ob_start();
include $this->__file;
$this->__content = ob_get_clean();
} catch (\Exception $ex) {
ob_end_clean();
throw $ex;
}
But it doesn't check if file really exists in file system. Which means that subsequent try { ... } catch(\Exception $ex) {...} block is useless, because include $this->__file; is uncatchable. So when I test my controllers I always get 200 response even if template file is missing and there is nothing but exception call stack on the screen. Shouldn't that if (!$this->__file) { ... } be rewritten to if (!is_file($this->__file)) { ... }?
Well, it's up to the resolver to perform these checks. See the following code taken from Zend\View\Resolver\TemplatePathStack:
foreach ($this->paths as $path) {
$file = new SplFileInfo($path . $name);
if ($file->isReadable()) {
// Found! Return it.
if (($filePath = $file->getRealPath()) === false && substr($path, 0, 7) === 'phar://') {
// Do not try to expand phar paths (realpath + phars == fail)
$filePath = $path . $name;
if (!file_exists($filePath)) {
break;
}
}
if ($this->useStreamWrapper()) {
// If using a stream wrapper, prepend the spec to the path
$filePath = 'zend.view://' . $filePath;
}
return $filePath;
}
}
Also note that include accepts more than is_file checks for. For instance, include also accepts stream wrappers.

Can I use try-catch-finally like this?

I'm using try-catch for years, but I never learned how and when to use finally, because I never understood the point of finally (I've read bad books)?
I want to ask you about use of finally in my case.
My code example should explain everything:
$s = "";
$c = MyClassForFileHandling::getInstance();
try
{
$s = $c->get_file_content($path);
}
catch FileNotFoundExeption
{
$c->create_file($path, "text for new file");
}
finally
{
$s = $c->get_file_content($path);
}
Is this correct use of finally?
More precise question:
Shall I use finally (in future PHP versions or other languages) for handling "create something if it not exists" operations?
Finally will always be executed, so in this case, it is not its intended purpose, since normal execution would reopen the file a second time. What you intend to do would be achieved in the same (cleaner) way if you do
$s = "";
$c = MyClassForFileHandling::getInstance();
try
{
$s = $c->get_file_content($path);
}
catch(FileNotFoundExeption $e)
{
$c->create_file($path, "text for new file");
$s = $c->get_file_content($path);
}
Then the manual says:
For the benefit of someone anyone who hasn't come across finally blocks before, the key difference between them and normal code following a try/catch block is that they will be executed even the try/catch block would return control to the calling function.
It might do this if:
code if your try block contains an exception type that you don't catch
you throw another exception in your catch block
your try or catch block calls return
Finally would then be useful in this kind of scenario:
function my_get_file_content($path)
{
try
{
return $c->get_file_content($path);
}
catch(FileNotFoundExeption $e)
{
$c->create_file($path, "text for new file");
return $c->get_file_content($path);
}
finally
{
$c->close_file_handler();
}
}
=> if you need to make sure you close your file handler in this case, or some resource in general.
finally wasn't introduced into PHP until version 5.5 which has not been released yet so that why you haven't seen any examples with it yet. So unless you're running and alpha version of PHP 5.5 you can't use finally yet.
From the manual (exceptions)
In PHP 5.5 and later, a finally block may also be specified after the catch blocks. Code within the finally block will always be executed after the try and catch blocks, regardless of whether an exception has been thrown, and before normal execution resumes.
Example from the manual of using finally
<?php
function inverse($x) {
if (!$x) {
throw new Exception('Division by zero.');
}
else return 1/$x;
}
try {
echo inverse(5) . "\n";
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
} finally {
echo "First finally.\n";
}
try {
echo inverse(0) . "\n";
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
} finally {
echo "Second finally.\n";
}
// Continue execution
echo 'Hello World';
?>
Finally means what do you want to DO Finally.
try
{
$s = $c->get_file_content($path);
}
catch FileNotFoundExeption
{
$c->create_file($path, "text for new file");
}
finally
{
//Create a pdf with my file
//or, Rename my file
//or, store my file into Database
}
No matter what happens(regardless of whether an exception has been thrown) inside try or catch, 'Finally code' will execute.
So, no point of using same code over 'try' and 'finally'.
Does this simply answer your question?
I just want to appoint that if an Exception occurs in the try block, the exception will be correctly raised even if the finally block is present.
The usefulness of the finally block is for clean and free resources.
I think it's best use is when, for example, you upload a file but then an error happens:
$tmp_name = null;
try {
$tmp_name = tempnam(UPLOAD_DIR, 'prefix');
move_uploaded_file($file['tmp_name'], $tmp_name);
ImageManager::resize($tmp_name, $real_path, $width, $height); // this will rise some exception
}
finally {
if($tmp_name)
unlink($tmp_name); // this will ensure the temp file is ALWAYS deleted
}
As you can see, in this way no matter what happen, the temp file will be correctly deleted.
If we would emulate the finally clause in older version of PHP, we should write something like this:
// start finally
catch(Exception $ex) {
}
if($tmp_name)
unlink($tmp_name);
if( isset($ex) )
throw $ex;
// end finally
Note that the exception has been re-thrown in case the catch block caught something. It isn't clear as the finally version, but works the same.

Error Handling with files in PHP

Error Handling with files in PHP
$path = '/home/test/files/test.csv';
fopen($path, 'w')
Here I want add an error handling by throwing exceptions, on 'No file or directory is found' and 'No permission to create a file'.
I am using Zend Framework.
By using fopen with write mode, I can create a file. But how to handle it when corresponding folder is not there?
i.e if files folder is not present in root structure.
How to throw an exception when no permission is permitted for creating a file?
Something like this should get you started.
function createFile($filePath)
{
$basePath = dirname($filePath);
if (!is_dir($basePath)) {
throw new Exception($basePath.' is an existing directory');
}
if (!is_writeable($filePath) {
throw new Exception('can not write file to '.$filePath);
}
touch($filePath);
}
Then to call
try {
createFile('path/to/file.csv');
} catch(Exception $e) {
echo $e->getMessage();
}
I suggest, you take a look at this link: http://www.w3schools.com/php/php_ref_filesystem.asp
especially the methods file_exists and is_writable
Like this:
try
{
$path = '/home/test/files/test.csv';
fopen($path, 'w')
}
catch (Exception $e)
{
echo $e;
}
PHP will echo whatever error would arise there.
Though you can also use is_dir or is_writable functions to see if folder exists and has permission respectively:
is_dir(dirname($path)) or die('folder doesnt exist');
is_writable(dirname($path)) or die('folder doesnt have write permission set');
// your rest of the code here now...
But how to handle it when corresponding folder is not there?
When a folder does not exist .. try to create it!
$dir = dirname($file);
if (!is_dir($dir)) {
if (false === #mkdir($dir, 0777, true)) {
throw new \RuntimeException(sprintf('Unable to create the %s directory', $dir));
}
} elseif (!is_writable($dir)) {
throw new \RuntimeException(sprintf('Unable to write in the %s directory', $dir));
}
// ... using file_put_contents!

Categories