Zend Framework

Zend_Cache::_isReadable() and Zend_Loader::isReadable() refactoring

Details

Description

Both Zend_Cache::_isReadable() and Zend_Loader::isReadable() code/performance could be improved using the new PHP 5.3.2 stream_resolve_include_path() function.

Zend_Cache::_isReadable() can be particularly slow due to error suppression so

private static function _isReadable($filename)
    {
        if (!$fh = @fopen($filename, 'r', true)) {
            return false;
        }
        @fclose($fh);
        return true;
    }

could be rewritten to:

private static function _isReadable($filename)
    {
        return is_string(stream_resolve_include_path($filename));
    }

or, for backward compatibility:

private static function _isReadable($filename)
    {
        if (function_exists('stream_resolve_include_path')) {
            return is_string(stream_resolve_include_path($filename));
        }

        if (!$fh = @fopen($filename, 'r', true)) {
            return false;
        }
        @fclose($fh);
        return true;
    }

Something similar applies to Zend_Loader

public static function isReadable($filename)
    {
        // NEW CODE

        if (function_exists('stream_resolve_include_path')) {
            return is_string(stream_resolve_include_path($filename));
        }
        
        // OLD CODE

        [....]

        foreach (self::explodeIncludePath() as $path) {
            if ($path == '.') {
                if (is_readable($filename)) {
                    return true;
                }
                continue;
            }
            $file = $path . '/' . $filename;
            if (is_readable($file)) {
                return true;
            }
        }
        return false;
    }

so that the foreach loop can be avoided with PHP 5.3.2.

Zend_Cache method comes from Zend_Loader (see #ZF-2891 for details) so it would make sense to extrapolate the code in a separate class, taking into consideration to use Zend_Loader code instead of the error suppression, something like this (comments removed for brevity):

class Zend_File
	{
	    public static function isReadable($filename)
	    {
	        if (function_exists('stream_resolve_include_path')) {
	            return is_string(stream_resolve_include_path($filename));
	        }

	        if (is_readable($filename)) {
	            return true;
	        }

	        if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN'
	            && preg_match('/^[a-z]:/i', $filename)
	        ) {
	            return false;
	        }

	        foreach (Zend_Application::getIncludePathArray() as $path) {
	            if ($path == '.') {
	                if (is_readable($filename)) {
	                    return true;
	                }
	                continue;
	            }
	            $file = $path . '/' . $filename;
	            if (is_readable($file)) {
	                return true;
	            }
	        }
	        return false;
	    }
	}

adding this to Zend_Application:

/**
	 * explodeIncludePath() method renamed to getIncludePathArray()
	 * Todo: Cache the result ?
	 */
    public static function getIncludePathArray($path = null)
    {
        if (null === $path) {
            $path = get_include_path();
        }

        if (PATH_SEPARATOR == ':') {
            $paths = preg_split('#:(?!//)#', $path);
        } else {
            $paths = explode(PATH_SEPARATOR, $path);
        }
        return $paths;
    }

To avoid confusion with PHP is_readable() function, why not renaming isReadable() to isAccessible() deprecating the old methods with a trigger_error('...', E_USER_NOTICE) ?

Activity

Hide
Matthew Weier O'Phinney added a comment -

Unfortunately, this cannot be a solution until 2.0 at the earliest; the 1.X branch has a minimum required version of PHP 5.2.4, meaning we cannot use PHP 5.3-specific solutions.

I'm marking the improvement as for "next major version".

Show
Matthew Weier O'Phinney added a comment - Unfortunately, this cannot be a solution until 2.0 at the earliest; the 1.X branch has a minimum required version of PHP 5.2.4, meaning we cannot use PHP 5.3-specific solutions. I'm marking the improvement as for "next major version".
Hide
Devis Lucato added a comment -

As a performance improvement, would it be possible to address the error suppression on ZF 1.x ?

It seems to be just a matter of copying the code from Zend_Loader::isReadable to Zend_Cache::_isReadable (as the PHP Doc in Zend_Cache says)

Show
Devis Lucato added a comment - As a performance improvement, would it be possible to address the error suppression on ZF 1.x ? It seems to be just a matter of copying the code from Zend_Loader::isReadable to Zend_Cache::_isReadable (as the PHP Doc in Zend_Cache says)
Hide
Marc Bennewitz (private) added a comment -
Show
Marc Bennewitz (private) added a comment - created pull request https://github.com/zendframework/zf2/issues#issue/94

People

Vote (0)
Watch (0)

Dates

  • Created:
    Updated: