I can't do this but wondering what would work:
is_object(new Memcache){
//assign memcache object
$memcache = new Memcache;
$memcache->connect('localhost', 11211);
$memcache->get('myVar');
}
else{
//do database query to generate myVar variable
}
You can use class_exists() to check if a class exists, but it will not return if you can instantiate that class!
One of the reasons you can't, might be that it is an abstract class. To check for that you should do something like this after you check for class_exists().
This might be impossible (having an abstract class, not checking for it) for above example, but in other situations might be giving you headaches :)
//first check if exists,
if (class_exists('Memcache')){
//there is a class. but can we instantiate it?
$class = new ReflectionClass('Memcache')
if( ! $class->isAbstract()){
//dingdingding, we have a winner!
}
}
See class_exists
if (class_exists('Memcache')){
//assign memcache object
$memcache = new Memcache;
$memcache->connect('localhost', 11211);
$memcache->get('myVar');
}
else{
//do database query to generate myVar variable
}
Check out class_exists().
http://php.net/manual/en/function.class-exists.php
You can use the class_exists function to see if a class exists or not.
See more in the manual: class_exists
The ReflectionClass::isInstantiable method checks if the class is instantiable.
$reflector = new ReflectionClass($concrete);
if ($reflector->isInstantiable()) {
// do something
}
Related
The ReflectionMethod instance from PHP (http://php.net/manual/en/class.reflectionmethod.php) has the getDocComment method that returns the annotation of a method. This works ok, unless you use unserialized object.
$ref = new ReflectionClass('a');
var_dump(method_exists($ref, 'getDocComment')); //bool(true)
var_dump($ref->getDocComment()); //bool(false)
$ref = unserialize(serialize($ref));
var_dump(method_exists($ref, 'getDocComment')); //bool(true)
var_dump($ref->getDocComment()); //PHP Warning: Uncaught Error: Internal error: Failed to retrieve the reflection object
Is there any way of testing if the ReflectionMethod object has correctly defined doc comment? I mean, I do not care about getting the annotation after serialize/unserialize, but I want to check if calling getDocComment is safe.
Edit: According to responses that advice error handling + fallback, I rephrase the Q.
I have some simple cache of reflections (array of ReflectionMethod objects). Until I use item from that cache, I wold like to chech its correctness. I do NOT want to handle error, I want to "predict error". Awesome would be something like hasDocComment method that does not generate any error, but returns only true/false within any ReflectionMethod object state.
The general approach of serializing reflection objects is wrong. There exists a PHP Bug report for it, but it has been set to "irrelevant":
https://bugs.php.net/bug.php?id=70719
The reason is, that you cannot connect a reflection object back to its class again, because you would have to deal with source code changes and all kinds of stuff. What you should do instead is, to serialize the name of the class and generate a NEW reflection object from that class, when you unserialize.
Code Example:
class A { }
$ref = new ReflectionClass('A');
var_dump(method_exists($ref, 'getDocComment'));
// serialize only the class name
$refClass = unserialize(serialize($ref->getName()));
// get a new reflection object from that class ...
$ref = new ReflectionClass($refClass);
var_dump(method_exists($ref, 'getDocComment'));
// If you want to serialize an object
$a = new A();
$a2 = unserialize(serialize($a));
$ref = new ReflectionClass(get_class($a2));
var_dump(method_exists($ref, 'getDocComment'));
If you need to be able to handle errors, you can try/catch the execution block. Since alt-php71-7.1.0-1 (which you seem to be using), this will throw an instance of Error instead of simply a Fatal Error, which allows you to do error handling.
<?php
class A { }
$ref = new ReflectionClass('A');
var_dump(method_exists($ref, 'getDocComment')); //bool(true)
var_dump($ref->getDocComment()); //bool(false)
// serialize only the class name
$refClass = unserialize(serialize($ref));
try {
$refClass->getDocComment();
// do your work
}
catch (Error $e) {
echo "Malformed Reflection object: ".$e->getMessage();
}
Demo
And since you can still get the class name from the malformed Reflection instance, you can instantiate a new one right in your catch block:
<?php
class A { }
$ref = new ReflectionClass('A');
var_dump(method_exists($ref, 'getDocComment')); //bool(true)
var_dump($ref->getDocComment()); //bool(false)
// serialize only the class name
$refClass = unserialize(serialize($ref));
try {
$refClass->getDocComment();
}
catch (Error $e) {
$recoveredRef = new ReflectionClass($refClass->getName());
var_dump($recoveredRef);
var_dump($recoveredRef->getDocComment()); // works correctly
echo "Malformed Reflection object, but recovered: ".$e->getMessage();
}
Demo
I've been trawling through the PHP docs trying to identify if there is any method that will allow me to differentiate between instances of a built-in class (such as DateTime or PDO) and User-defined Classes, but without any success.
The only approach that I have found so far is to try and bind a closure to the instance. When doing this with a built-in class, it displays a warning (yuk) and returns a null.
$targetObject = new DateTime();
$closure = function();
$test = #$closure->bindTo($targetObject, get_class($targetObject));
if ($test === false) {
throw new Exception('General failure');
} elseif ($test === null) {
throw new Exception('Unable to bind to internal class');
}
Is anybody aware of a cleaner approach to this problem?
Take a look at the reflection API. Manual
<?php
$d = new DateTime();
$r = new ReflectionClass($d);
echo ($r->isInternal());
This seems like a fairly simple reflection problem, yet I can't figure it our. I use Laravel 4.2 on Debian with PHP 5.6.6-1.
Basicly what happens is that I want to spawn a new object from a class in a Laravel QueueHandler like so:
$className = 'MyClass';
$myobject = new $className ();
and this doesn't work. I tried everything I can possibly think of and have no clue where to look. This code doesn;t work while it should:
<?php
use Pronamic\Twinfield\Secure\Config;
use Pronamic\Twinfield\Customer\CustomerFactory;
class TwinfieldQueueHandler {
private $twinfieldConfig = null;
...
try {
$twinfieldFactoryClass = 'CustomerFactory';
//returns 0
echo strcmp('CustomerFactory', $twinfieldFactoryClass);
//works
$test0 = new CustomerFactory ($this->twinfieldConfig);
//throws an exeption with message: "Class CustomerFactory does not exist"
$r = new ReflectionClass($twinfieldFactoryClass);
$test1 = $r->newInstanceArgs($this->twinfieldConfig);
//gives error PHP Fatal error: Class 'CustomerFactory' not found in {file} on line {line}
$test2 = new $twinfieldFactoryClass ($this->twinfieldConfig);
} catch (Exception $e) {
Log::error($e->getMessage());
}
Has anyone got any pointers on where to look and how to debug this?
ReflectionClass will ignore your current namespace and use statements completely. You have to specify the fully qualified name of the class:
$r = new ReflectionClass('Pronamic\Twinfield\Customer\CustomerFactory');
As a user points out on php.net:
To reflect on a namespaced class in PHP 5.3, you must always specify the fully qualified name of the class - even if you've aliased the containing namespace using a "use" statement.
Note that you could work around this by passing an object:
$test0 = new CustomerFactory ($this->twinfieldConfig);
$r = new ReflectionClass($test0);
I'm sorry for the lack of information on this question I just need some advice on some code. I think only a programmer can answer this because my code is unique and I couldn't find any answers that help me.
Index.php
<?php
include ( 'Blue/BlueDatabase.php' );
include ( 'Blue/BlueUsers.php' );
use Blue\BlueDatabase;
use Blue\BlueLoader;
$database = new BlueDatabase();
$database->Connect('localhost', 'root', '', 'database');
?>
And now I have my "BlueLoader" class and I have this code in the class aswell
$database = new BlueDatabase();
$database->Connect('localhost', 'root', '', 'database');
What I want to know is. Is it worth adding that code to every class? It makes it look untidy and I think there will be a more stabler way of doing it. Do i need to do the connect function once ive done it before? does it need to be done for every class? I'm just new to php and unsure about some things. Is this script stable? / Secure
Any advice or answers will be helpful
Just incase you need my connect function (All my mysql commands are in an array like
//Example:
$commands['mysql_query'] = mysql_query;
final public function connect($sHost, $sUser, $sPass, $sName, $sPort = false, $sType = 'mysql_connect')
{
if(!$this->connected)
{
if ($sPort)
{
$sHost = $sHost . ':' . $sPort;
}
$this->connection = $this->_aCmd[$sType]($sHost, $sUser, $sPass);
if($this->connection)
{
$mydatabase = $this->_aCmd['mysql_select_db']($sName, $this->connection);
if($mydatabase)
{
$this->connected = true;
}
else
{
die('could not connect to database');
}
}
else
{
die('could not connect to host');
}
}
}
Advice:
Stop using the deprecated ext/mysql extension. Don't bother trying to wrap it in an OO framework.
Use PDO, because it already has a good OO usage, and has several other features that ext/mysql doesn't have. Mysqli is a runner-up, but I find PDO is easier to use.
Don't open a new connection in each class that uses a database. Create one connection and pass the connection object to each such class, probably as a constructor argument.
An alternative is to use a Registry class to store "global" objects like database connections.
Globals are great! They are perfect for indicating that you're taking a sub-optimal approach and you need to step back and re-evaluate.
Here are a few different ways you can address the issue.
$dbh = new DatabaseObject($connection_info);
$foo = new Object1($dbh);
$bar = new Object2();
$bar->GiveDbh($dbh);
$baz = new RegistryObject();
$baz->register('dbh', $dbh);
$bom = new Object3($baz);
I'd also include a Singleton method, but SO yells at me every time I do. :/
Also, you should probably re-jigger your database class to stop using mysql_* functions. Yadda yadda PDO MySQLi, you know the drill.
I have
$test = 'SomeClass';
$ins = new $test;
I want to be able to catch the error if the name for $test doesn't exist.
I'm not sure what type of exception it threw as PHP didn't gave me anything.
Use class_exists().
Check first like this:
if(class_exists($test)){
$ins = new $test;
}else{
die("Could not load class'" . $test ."'");
}
Such a construction won't let you catch any errors unless you use some error handler. However you can check whether class exists or not using class_exists() function.
PS. You should use reflection as it is much more verbose and clear. Also it uses exceptions so you can do something like:
try {
$ref = new \ReflectionClass($className);
} catch (\LogicException $le) {
// class probably doesn't exist
}
With PHP 5.3 (or greater), you can catch exceptions thrown from __autoload
function __autoload($name) {
// if class doesn't exist:
throw new Exception("Class $name not found");
// else, load class source
}
$test = 'SomeClass';
try {
$ins = new $test;
} catch (Exception $e) {
}
first, you must test if $test class exists.
http://php.net/manual/en/function.class-exists.php