How can i check to see if a static class has been declared?
ex
Given the class
class bob {
function yippie() {
echo "skippie";
}
}
later in code how do i check:
if(is_a_valid_static_object(bob)) {
bob::yippie();
}
so i don't get:
Fatal error: Class 'bob' not found in file.php on line 3
You can also check for existence of a specific method, even without instantiating the class
echo method_exists( bob, 'yippie' ) ? 'yes' : 'no';
If you want to go one step further and verify that "yippie" is actually static, use the Reflection API (PHP5 only)
try {
$method = new ReflectionMethod( 'bob::yippie' );
if ( $method->isStatic() )
{
// verified that bob::yippie is defined AND static, proceed
}
}
catch ( ReflectionException $e )
{
// method does not exist
echo $e->getMessage();
}
or, you could combine the two approaches
if ( method_exists( bob, 'yippie' ) )
{
$method = new ReflectionMethod( 'bob::yippie' );
if ( $method->isStatic() )
{
// verified that bob::yippie is defined AND static, proceed
}
}
bool class_exists( string $class_name [, bool $autoload ])
This function checks whether or not the given class has been defined.
Related
I created a class. The code is below
class Another {
public $error = array();
public function set_error( $key, $value )
{
if ( isset( $key ) ) {
$sanitizedKey = sanitize_key( $key );
$this->error[ $sanitizedKey ] = wp_json_encode( $value );
return $this->error;
}
}
public function get_error( $id )
{
if ( ! is_null( $id ) ) {
return $this->error[ $id ];
}
}
public function print_error()
{
if ( $this->error ) {
foreach ($this->error as $key => $value) {
$decodeJson = json_decode( $value );
?>
<div class="ud-error">
<p class="ud-error-<?php echo $key; ?>">
<?php echo __( $decodeJson, 'ud-for-edd' ); ?>
</p>
</div>
<?php
}
}
}
}
If I invoke it in the following way it works. It echos the content as expected.
$error = new Another();
$error->set_error('gg', 'hhhh');
$error->print_error();
But if I use it with function then it doesn't work as expected. Do I have to pass parameters by reference or any other? The following way it doesn't work
function create_error($id, $val) {
$errr = new Another();
return $errr->set_error($id, $val);
}
create_error('raa', 'raashid');
$error = new Another();
$error->print_error();
I am confused about why this doesn't work. Any clue. Thanks in advance.
Steps I want the code to perform:
Create a class with 3 methods, set_error, get_error, and print_error
Then invoke the class inside the function. The function will accept two parameters because inside the class the set_error() method accepts two parameters.
In order to print the error, I will instantiate the class and call the print_error() method.
In case, if I have to print the new error. I will just call the create_error() function to do this for me. Because the function needs 2 parameters. The arguments supplied to the function must be supplied as arguments to the set_error() method.
I hope the list helps.
Update:
If I use a global variable then it works. Below is working.
$customError = new Another();
function create_error($id, $val) {
global $customError;
$customError->set_error($id, $val);
}
create_error('raa', 'rashid');
$customError->print_error();
Thanks, #roggsFolly and #El_Vanja. By understanding your tips I was able to solve the error. If there is anything wrong with the code I just said worked. Please point out.
The object you instantiate inside the function is not the same one you try and print the error message from.
First the object you instantiate inside the function scope is not visible outside the function.
function create_error($id, $val) {
$errr = new Another();
return $errr->set_error($id, $val);
}
create_error('raa', 'raashid');
// this instantiates a seperate Another object from the one
// you created in the function
$error = new Another();
// this tries to print from the new object taht has no message stored in it yet
$error->print_error();
To instantiate the object inside a function scope and then use that object outside the function scope you must pass that object back to the caller of the function
function create_error($id, $val) {
$errr = new Another();
$errr->set_error($id, $val);
return $errr; // this returns the object
}
$error = create_error('raa', 'raashid');
// now you can use its methods to print the stored message
$error->print_error();
Update as per your additional Information
A couple of things I think you may be getting confused about.
Each time you do $var = new ObjectName; you are creating a brand new instance of that class. This new instance has no knowledge about any other instances of that class that may or may not have been created before or may be created after that point. And more specifically to your problems, it does not have access to the properties of another version of that object.
You are I believe missing the concept of variable scope. The Object you create inside that function, will only actually exist while the function is running. Once the function completes anything created/instantiated wholly within that function is DESTROYED ( well in truth it is just no longer accessible ) but to all intent and purpose it is destroyed. you therefore cannot expect to be able to address it outside the scope of the function.
If you want the Object you instantiate within the function to be usable outside the function, you must pass a reference to that object out of the function to the calling code. This passes that reference into the scope of the calling code and keeps the object alive, global scope in your case, but that might be another function or even another object. That allows you access to that instantiation and any properties that were set within it.
I get the following error on my WP Dashboard:
Warning: First parameter must either be an object or the name of an existing class
in /home/content/88/11746388/html/wp-content/plugins/pluginname/pluginname.php on
line 136
Those are my lines from 130 to 140. Any ideas?
function get_latest_version($plugin_file) {
$latest_version = '';
$sr_plugin_info = get_site_transient ( 'update_plugins' );
// if ( property_exists($sr_plugin_info, 'response [$plugin_file]') && property_exists('response [$plugin_file]', 'new_version') ) {
if ( property_exists($sr_plugin_info, 'response [$plugin_file]') ) {
$latest_version = $sr_plugin_info->response [$plugin_file]->new_version;
}
return $latest_version;
}
it seems that you have error in this line :
if ( property_exists($sr_plugin_info, 'response [$plugin_file]') ) {
property_exists — Checks if the object or class has a property .
and 'response [$plugin_file]' it is not a valid property name of class.
To be honest that code is bleeding from several wounds.
a.) get_site_transient is not guaranteed to return an object and property_exists expects one
b.) you try to check if an array key exists in a property with property_exists. I'm fairly certain that property_exists can not do that - you should only check for response property with it and use isset() for the $plugin_file index.
function get_latest_version($plugin_file) {
$latest_version = '';
$sr_plugin_info = get_site_transient ( 'update_plugins' );
// if ( property_exists($sr_plugin_info, response[$plugin_file]) && property_exists(response[$plugin_file], 'new_version') ) {
if ( property_exists($sr_plugin_info, response[$plugin_file]) ) {
$latest_version = $sr_plugin_info->response[$plugin_file]->new_version;
}
return $latest_version;
}
This question already has answers here:
How do I catch a PHP fatal (`E_ERROR`) error?
(18 answers)
Is it possible in PHP to prevent "Fatal error: Call to undefined function"?
(7 answers)
Closed 9 years ago.
I'm learning my way into some more advanced programming with PHP.
I've seen that calling an non-existent method produces "call to undefined method" error.
PHP being quite flexible is there a technique that allows to intercept this error ? If so, how is this usually done ?
Edit: To clarify, I want to actually do something when the error occurs like send a reply back, not necessarily prevent it. Forget to mention that this is in the context of a class. Of course, methods only apply in the context of a class ;)
Yes, it's possible to trap calls to undefined methods of classes using magic methods:
You need to implement the __call() and/or __callStatic() methods as defined here.
Suppose you have a simple class CCalculationHelper with just a few methods:
class CCalculationHelper {
static public function add( $op1, $op2 ) {
assert( is_numeric( $op1 ));
assert( is_numeric( $op2 ));
return ( $op1 + $op2 );
}
static public function diff( $op1, $op2 ) {
assert( is_numeric( $op1 ));
assert( is_numeric( $op2 ));
return ( $op1 - $op2 );
}
}
At a later point of time, you need to enhance this class by multiplication or division. Instead of using two explicit methods, you might use a magic method, which implements both operations:
class CCalculationHelper {
/** As of PHP 5.3.0 */
static public function __callStatic( $calledStaticMethodName, $arguments ) {
assert( 2 == count( $arguments ));
assert( is_numeric( $arguments[ 0 ] ));
assert( is_numeric( $arguments[ 1 ] ));
switch( $calledStaticMethodName ) {
case 'mult':
return $arguments[ 0 ] * $arguments[ 1 ];
break;
case 'div':
return $arguments[ 0 ] / $arguments[ 1 ];
break;
}
$msg = 'Sorry, static method "' . $calledStaticMethodName . '" not defined in class "' . __CLASS__ . '"';
throw new Exception( $msg, -1 );
}
... rest as before...
}
Call it like so:
$result = CCalculationHelper::mult( 12, 15 );
Seeing how you don't wish to recover from these fatal errors, you can use a shutdown handler:
function on_shutdown()
{
if (($last_error = error_get_last()) {
// uh oh, an error occurred, do last minute stuff
}
}
register_shutdown_function('on_shutdown');
The function is called at the end of your script, regardless of whether an error occurred; a call to error_get_last() is made to determine that.
If you mean how to intercept non-existent method in a your custom class, you can do something like this
<?php
class CustomObject {
public function __call($name, $arguments) {
echo "You are calling this function: " .
$name . "(" . implode(', ', $arguments) . ")";
}
}
$obj = new CustomObject();
$obj->HelloWorld("I love you");
?>
Or if you want to intercept all the error
function error_handler($errno, $errstr, $errfile, $errline) {
// handle error here.
return true;
}
set_error_handler("error_handler");
I want to create a smarter way to create if statements. I'm writing a function to do this:
if ( ! function_exists( 'get_meta' ) ) {
function get_meta($i) {
$fname_name = array(
'copyright_text',
'about_name',
'archive_name',
'contact_name',
'lenguage_name',
'cc_name',
'about_link',
'archive_link',
'contact_link',
'lenguage_link',
'cc_link',
'about_editors_name',
'about_responsibility_name',
'about_joinus_name',
'about_editors_link',
'about_responsibility_link',
'about_joinus_link'
);
foreach( $fname_name as $fname )
include_once( get_option($fname));
if ( $i ) return $fname_name[$i];
}
}
But when this function is called, it returns this error:
Warning: include_once() [function.include]: Failed opening 'what' for inclusion (include_path='.;php\PEAR') in local\wp-content\themes\net\0.6\functions.php on line 398
Basically, just want to add get_option(''); to each array, to return for example:
get_option('copyright_text');
or even more specific, to return:
get_option('copyright_text', '');
FIXED:
Okay, I just fix this by myself, but I'm so grateful of any advice here.
Instead using foreach and include_once, I use an even more simple solution:
if ($i) return get_option($fname_name[$i], '');
else if ($i == 0) return get_option($fname_name[0], '');
use this
foreach( $fname_name as $fname ){
include_once( get_option($fname));
if ( $i ) return $fname;
}
This looks like you are creating a shortcut for writing accessor methods. You would do yourself some good to take a look at PHP's magic methods. Specifically pay attention to __get, __set, and __call.
http://php.net/manual/en/language.oop5.magic.php
In this case, what you are doing looks similiar to the following:
class myClass {
// This could be associated with whatever other data you are interested in
private $_meta = array(
'copyright_text',
'about_name',
'archive_name',
'contact_name',
'lenguage_name',
'cc_name',
'about_link',
'archive_link',
'contact_link',
'lenguage_link',
'cc_link',
'about_editors_name',
'about_responsibility_name',
'about_joinus_name',
'about_editors_link',
'about_responsibility_link',
'about_joinus_link'
);
public function __get($name) {
if (in_array($name, $this->_meta)) {
return $this->_meta[$name];
}
}
}
I'm working with a script that is calling the same class twice and throwing the error:
Fatal: Cannot redeclare class urlConverter (/var/www/core/cache/includes/elements/modsnippet/23.include.cache.php:14)
I have tried placing the following code in:
if( !class_exists( 'urlConverter', false ) )
{
$urlConverter = new urlConverter( $modx );
}
However doing that the CMS I'm working with is reporting an Error 500 and haven't been able to see in the logs why it's throwing that error.
Does anyone know how to check if that class has already been declared correctly?
Edit:
I'm using a CMS so as a result the Class is housed in a Snippet and not an actual file. This is how they call their snippets:
$data['viewonlinelink'] = $this->modx->runSnippet( 'urlConverter', array(
'action' => 'encrypt',
'string' => http_build_query( $string ) ) );
I need to call that a second time to get a different result.
Edit2:
Here is urlConverter:
<?php
class urlConverter {
public $modx;
public function __construct( modX &$modx )
{
$this->modx =& $modx;
}
public function action( $scriptProperties )
{
return $this->$scriptProperties['action']( $scriptProperties['string'] );
}
private function encrypt( $str )
{
return $str;
}
private function decrypt( $str )
{
return $str;
}
}
}
$urlConverter = new urlConverter( $modx );
return $urlConverter->action( $scriptProperties );
Now from another script I call the following:
$data['viewonlinelink'] = $this->modx->runSnippet( 'urlConverter', array(
'action' => 'encrypt',
'string' => http_build_query( $string ) ) );
$data['confirmonline'] = $this->modx->runSnippet( 'urlConverter', array(
'action' => 'encrypt',
'string' => http_build_query( $reversed ) ) );
Which runs the function encrypt inside of my urlConverter class and I should receive two different results.
In using your updated code, change the class file to this:
<?php
if(!class_exists('urlConverter')){
class urlConverter {
public $modx;
public function __construct( modX &$modx ){
$this->modx =& $modx;
}
public function action( $scriptProperties ){
return $this->$scriptProperties['action']( $scriptProperties['string'] );
}
private function encrypt( $str ){
return $str;
}
private function decrypt( $str ){
return $str;
}
}
}
$urlConverter = new urlConverter( $modx );
return $urlConverter->action( $scriptProperties );
The redeclare class error is not caused by creating a new instance of the class, it's called by invoking the class operator on the same symbol. You're probably including the urlConverter class definition file multiple times.
If you cannot modify the way your class file is brought into the CMS (by using require_once or include_once), modify your snippet:
if( !class_exists( 'urlConverter' ) ) {
class urlConverter {
/* Build class */
}
}
Of course if you have anything else in that same file, you'll want to make sure it doesn't try to run twice.
It looks like the file that defines the class is being included more than once which is why you are getting the first error (cannot redeclare class).
/var/www/core/cache/includes/elements/modsnippet/23.include.cache.php line 14 seems to be what is including the class multiple times. If possible, change the include to include_once so you don't define the class multiple times.
To debug further (instead of seeing the 500 internal server error), try adding the following to your code as early as possible:
error_reporting(E_ALL);
ini_set('display_errors', 1);
Otherwise, check the servers error_log (Apache) and see if there is any useful information there about the 500 error.