How do I from PHP code if a PECL extension is installed or not?
I want gracefully handle the case when an extension is not installed.
I think the normal way would be to use extension-loaded.
if (!extension_loaded('gd')) {
// If you want to try load the extension at runtime, use this code:
if (!dl('gd.so')) {
exit;
}
}
get_loaded_extensions fits the bill.
Use like this:
$ext_loaded = in_array('redis', get_loaded_extensions(), true);
Have you looked at get_extension_funcs?
Couple different ways. You can just check for the existence of the class, or even a function: class_exists, function_exists, and get_extension_funcs:
<?php
if( class_exists( '\Memcached' ) ) {
// Memcached class is installed
}
// I cant think of an example for `function_exists`, but same idea as above
if( get_extension_funcs( 'memcached' ) === false ) {
// Memcached isn't installed
}
You can also get super complicated, and use ReflectionExtension. When you construct it, it will throw a ReflectionException. If it doesnt throw an exception, you can test for other things about the extension (like the version).
<?php
try {
$extension = new \ReflectionExtension( 'memcached' );
} catch( \ReflectionException $e ) {
// Extension Not loaded
}
if( $extension->getVersion() < 2 ) {
// Extension is at least version 2
} else {
// Extension is only version 1
}
Related
I did an upgrade from typo3 4.5.0 to 6.2.14 and I get an issue with a custom extension which one of its functionality is to include custom plugins that are stored in extensions directory.
The plugins that are going to be included used the code below. The location of this code is in extensionkey/ext_tables.php
if (file_exists($path) && is_dir($path)) {
$files = scandir($path);
foreach ($files as $f) {
if (is_dir($path.$f) && $f!='.' && $f!='..' && $f!='.svn') {
$TCA['tt_content']['types']['list']['subtypes_excludelist'][$_EXTKEY.'_'.$f]='layout,select_key,pages';
$confArr = array('LLL:EXT:extensionkey/locallang_db.xml:tt_content.list_type_'.$f, $_EXTKEY.'_'.$f, '');
t3lib_extMgm::addPlugin($confArr,'list_type');
}
}
}
Please enable the "Development Mode" in the install tool, then you will see all errors. t3lib_extMgm::addPlugin does not exist in TYPO3 6.2 anymore and should result in an exception. It must be replaced with \TYPO3\CMS\Extbase\Utility\ExtensionManagementUtility
I should change sphinxapi.php , my sphinxapi.php on (usr/local/sphinx/lib/sphinxapi.php) i changed it but what should i do after that to use new functions ?
my php :
<?php
$sphinx = new SphinxClient();
$sphinx->SetServer($this->config->sphinx->host, $this->config->sphinx->port);
$sphinx->SetMatchMode(SPH_MATCH_ALL);
$sphinx->SetLimits(0, 1,1);
..filters...
$sphinx->RemoveFilter($color['id']);
My new function :
function RemoveFilter ( $attribute )
{
assert ( is_string($attribute) );
foreach($this->_filters AS $key => $filter){
if($filter['attr'] == $attribute){
unset($this->_filters[$key]);
break;
}
}
}
Error :
Fatal error: Call to undefined method SphinxClient::RemoveFilter() in
At a guess, you've modified the one that comes with sphinx, but the application itself is using a different 'sphinxapi.php' - maybe a locally installed one.
Or even you have the sphinx extension installed, so its providing the SphinxClient not 'sphinxapi.php`'- if so uninstall the extension.
Is there any way to determine whether FirePHP is installed on the server (via PEAR)? I'd like to make possible logging in FirePHP but also not to crash the code for everyone without that tool.
The example, how I imagine it should work:
$message = "hello";
function log($message) {
if (library_exists('FirePHPCore/fb.php')) {
require_once('FirePHPCore/fb.php');
ob_start();
\FB::log($message);
} else {
SomeBoringLogger::log($message);
}
}
I haven't found anything like my library_exists method. Is there anything like that in PHP?
#include_once('FirePHPCore/fb.php'); // Ignore any errors here, as we check for existance
if (class_exists('FirePHP')) { // Do something after this
http://php.net/manual/en/function.class-exists.php
FirePHP uses FirePHP as its class name, so if it is available, that class should be defined
For PHP 5.3.2 or later, use zerkms's suggestion:
(!stream_resolve_include_path('FirePHPCore/fb.php')===FALSE)
Use include_once, so it doesn't kill the request. As #Brad suggests, use class_exists afterwards.
$message = "hello";
safe_include_once('FirePHPCore/fb.php');
if (class_exists('FB')) {
function log($message) {
//using FirePHP
}
} else {
function log($message) {
SomeBoringLogger::log($message);
}
}
function safe_include_once($path) {
if ($path = stream_resolve_include_path($path)) {
include_once($path);
}
}
[Edit] Using stream_resolve_include_path in safe_include_path.
[Edit2] Faster runtime logging.
file_exists() can be used for your case.
I'm trying to write some code to track dependencies. Is there a way to programatically detect if a PEAR package has been installed? I'm thinking something like:
if ($some_pear_api->isPackageInstalled('FooPack')) {
echo 'FooPack is installed!';
} else {
echo 'FooPack is not installed. :(';
}
I know you can simply detect if the class file for that package exists, but I mostly want to know if PEAR has that installed because sometimes some libraries provide other means of including their code (e.g. PHPUnit has a pear channel as well as a git repo.).
Thanks for the help!
You need to use the PEAR_Registry class to do this (which is what the PEAR script itself uses).
Read Adam Harvey's blog post "pear -> list" from 3 years ago - all the details/examples you need are there.
include 'PEAR/Registry.php';
$reg = new PEAR_Registry;
foreach ($reg->listPackages() as $package) {
print "$package\n";
}
If you need this to check for specific versions of each package, then you could base something on the following example, which I provided in a comment to that blog entry:
<?php
require 'PEAR/Registry.php';
$reg = new PEAR_Registry;
define("NAME", 0);
define("VERSION", 1);
$packages = array(
array("PEAR", "1.6.2"),
array("Date", "1.4.7"),
array("Date_Holidays", "0.17.1"),
array("Validate_IE", "0.3.1")
);
foreach ($packages as $package) {
$pkg = $reg->getPackage($package[NAME]);
$version = $pkg->getVersion();
echo "{$package[NAME]} – {$package[VERSION]} – ";
echo version_compare($version, $package[VERSION], '>=') ? 'OK': 'BAD', "\n";
}
?>
If you need to copy and paste this, then it might be best for you to use the version at https://gist.github.com/kenguest/1671361.
You can use Pear/Infos packageInstalled to answer this:
<?php
require_once 'PEAR/Info.php';
$res = PEAR_Info::packageInstalled('FooPack');
if ($res) {
print "Package FooPack is installed \n";
} else {
print "Package FooPack is not yet installed \n";
}
?>
Why not just include the package and see if the class exists?
// Supress Errors. Checking is done below.
#require_once 'PHP/UML.php';
if(!class_exists('PHP_UML'))
{
throw new Exception('PHP_UML is not installed. Please call `pear install PHP_UML` from the command line',1);
}
// Code to use PHP_UML below...
$uml = new PHP_UML();
I'm working on some new components in my framework for a gettext implementation. It needs to support the dead php4 and php5+. I'm using Zend_Translate and I will implement a gettext based class for php4.
I'm wondering if it's ok to rely on the phpversion function to branch out on which class to implement. Something like...
$version = phpversion();
define('VERSION', grabVersion($version) ); // grab major version
if ( VERSION >= 5 ) {
$local = new Zend_Translate();
} else {
$local = new Gettext();
}
Both classes have a _ function to do the translations, so the rest should be the same.
<label for="first_name"><?php echo $local->_("First Name");?></label>
Is it common to do so in any of the major php frameworks, would you do something similar if you were forced to support the dead PHP4?
If I was going to implement this across PHP versions, I would rely on the version number too. So what you're proposing seems perfectly sane and acceptable.
It's not a terrible idea to branch on a php version number, but I would prefer something like this:
if(class_exists("Zend_Translate")) {
$local = new Zend_Translate();
} else if(class_exists("Gettext")) {
$local = new Gettext();
} else {
throw new Exception("No supported translation helper found");
}
If you wanted to, you could make it more dynamic:
$translators = array(
"Zend_Translate",
"Gettext",
"FooTranslate",
);
$local = null;
foreach($translators as $t) {
if(class_exists($t)) {
$local = new $t();
break;
}
}
if($local === null) {
throw new Exception("No supported translation helper found");
}
A better place to branch based on version, is error handling - above I use exceptions, which are not available in PHP4 :)
I think getting the version number is a good idea, but it should be implicit so it's not called out of the blue.
$local = TranslateFactory::create();
$local->_("translate me");
class TranslateFactory {
private static $_translator;
private static function _getTranslator() {
if(empty(self::$_translator)) {
// get php version
// if-case here
self::$_translator = // result your if-case
}
return self::$_translator;
}
public static function create() {
return _getTranslator();
}
}
That provides a per-request cache at least. The _getTranslator() could even fetch object from a longer lasting cache if you'd need it, just by putting the logic in that one spot fetching your real object.