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];
}
}
}
Related
I have several interchangeable functions with different numbers of arguments, for example:
function doSomething1($arg1) {
…
}
function doSomething2($arg1, $arg2) {
…
}
I would like to pass a certain number of these functions, complete with arguments, to another handling function, such as:
function doTwoThings($thing1, $thing2) {
$thing1();
$thing2();
}
Obviously this syntax is not correct but I think it gets my point across. The handling function would be called something like this:
doTwoThings(‘doSomething1(‘abc’)’, ‘doSomething2(‘abc’, ‘123’));
So the question is, how is this actually done?
From my research it sounds like I may be able to "wrap" the "doSomething" function calls in an anonymous function, complete with arguments and pass those "wrapped" functions to the "doTwoThings" function, and since the anonymous function doesn't technically have arguments they could be called in the fashion shown above in the second code snippet. The PHP documentation has me confused and none of the examples I'm finding put everything together. Any help would be greatly appreciated!
you could make use of call_user_func_array() which takes a callback (eg a function or class method to run) and the arguments as an array.
http://php.net/manual/en/function.call-user-func-array.php
The func_get_args() means you can feed this funciton and arbitary number of arguments.
http://php.net/manual/en/function.func-get-args.php
domanythings(
array( 'thingonename', array('thing','one','arguments') ),
array( 'thingtwoname', array('thing','two','arguments') )
);
funciton domanythings()
{
$results = array();
foreach( func_get_args() as $thing )
{
// $thing[0] = 'thingonename';
// $thing[1] = array('thing','one','arguments')
if( is_array( $thing ) === true and isset( $thing[0] ) and is_callable( $thing[0] ) )
{
if( isset( $thing[1] ) and is_array( $thing[1] ) )
{
$results[] = call_user_func_array( $thing[0], $thing[1] );
}
else
{
$results[] = call_user_func( $thing[0] );
}
}
else
{
throw new Exception( 'Invalid thing' );
}
}
return $results;
}
This would be the same as doing
thingonename('thing','one','arguments');
thingtwoname('thing','two','arguments');
How can we check for anonymous functions inside PHP arrays?
Example:
$array = array('callback' => function() {
die('calls back');
});
Can we then just simply use in_array, and to something like this:
if( in_array(function() {}, $array) ) {
// Yes! There is an anonymous function inside my elements.
} else {
// Nop! There are no anonymous function inside of me.
}
I'm experimenting with method chaining and PHP's Magic Methods, and I've come to the point where I provide some functions anonymously, and just want to check if they are defined, but I wish not to loop through the object, nor to use gettype, or anything similar.
You can filter the array by checking if the value is an instance of Closure:
$array = array( 'callback' => function() { die( 'callback'); });
$anon_fns = array_filter( $array, function( $el) { return $el instanceof Closure; });
if( count( $anon_fns) == 0) { // Assumes count( $array) > 0
echo 'No anonymous functions in the array';
} else {
echo 'Anonymous functions exist in the array';
}
Pretty much, just check if the element of the array is an instance of Closure. If it is, you have a callable type.
Nickb's answer is great for figuring out if it is an anonymous function, but you may also use is_callable to figure out if it is any type of function ( probably more safe to assume )
For example
$x = function() { die(); }
$response = action( array( $x ) );
...
public function action( $array ){
foreach( $array as $element )
if( is_callable( $element ) )
....
}
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.
In PHP, say that you have some code like this:
$infrastructure = mt_rand(0,100);
if ($infrastructure < $min_infrastructure) $infrastructure = $min_infrastructure;
//do some other stuff with $infrastructure
$country->set_infrastructure($infrastructure);
$education = mt_rand(0,100);
if ($education < $min_education) $education = $min_education;
//do some other stuff with $education
$country->set_education($education);
$healthcare = mt_rand(0,100);
if ($healthcare < $min_healthcare) $healthcare = $min_healthcare;
//do some other stuff with $healthcare
$country->set_healthcare($healthcare);
Is there some way of combining these similar sets of instructions into a function that could be called like:
change_stats("infrastructure");
change_stats("education");
change_stats("healthcare");
Basically, can you use variables in PHP in other variable names and function names?
Thanks in advance.
You can use what PHP calls "variable variables" to do this. I hope your example is contrived, as it looks a bit odd, but assuming the variables and objects are global, you could write the name_pet() function like this:
function name_pet($type, $name)
{
$class='the_'.$type;
$var=$type.'_name';
$GLOBALS[$class]->setName($name);
$GLOBALS[$var]=$name;
}
EDIT: this answer refers to an earlier version of the question.
Yes, it is possible, take a look here for a discussion and here for a tutorial.
To answer your question: Yes, you can use variables as variable names, using the ${$varname} syntax.
However, that does not seem to be a proper solution for what you are trying to do here, as setting the $the_{$petname} variables requires them to be in the scope of the name_pet function.
Could you elaborate a bit more on what it is that you are trying to do?
Some suggestions: Have the pet class (or whatever it is that the cat, dog and fish are) return the name that is being set, so you can do $fish_name = $the_fish->setName("Goldie");
Or even better, not use $fish_name at all, since that information is now stored in the object... you could simply call $the_fish->getName(); where you'd use $the_fish.
Hope this helps?
I'm not sure about that function but you could do something similar using __set
$data;
function __set($key, $val) {
$this->data["$key"] = $val;
}
And yes you can use variables dynamically
$foo = "bar";
$dynamic = "foo";
echo $$dynamic; //would output bar
echo $dynamic; //would output foo
This is an interesting question because this is a common pattern and is especially important to watch out for when refactoring.
In the purely functional way, you can use some code like this:
function rand_or_min( $value, $key, $country ) {
$rand = mt_rand(0,100);
if ($rand < $value ) { $rand = $value; }
// do something
call_user_func( array( $country, 'set_' . $value ), array( $rand ) );
}
$arr = array('infrastructure' => 5,'education' => 3,'healthcare' => 80);
array_walk( $arr, 'rand_or_min', $country );
Though the above works well, I would highly recommend that you use a more object oriented path. Whenever you see a pattern like the above, you should be thinking classes and sub-classes. Why? Because there is duplicated behavior and similar state (variables).
In a more OOP way, this could be implemented like so:
class SomeBasicBehavior {
function __construct( $min = 0 ) {
$rand = mt_rand(0,100);
if( $rand < $min ) { $rand = $min };
return $rand;
}
}
class Infrastructure extends SomeBasicBehavior {
}
class Education extends SomeBasicBehavior {
}
class Healthcare extends SomeBasicBehavior {
}
$country->set_infrastructure( new Infrastructure() );
$country->set_education( new Education() };
$country->set_healthcare( new Healthcare() };
Not only is it much more readable, but it's also much more extensible and testable. Your "do something" can be easily implemented as member functions in each class and their behavior can be as shared as needed (using the SomeBasicBehavior class) or as encapsulated as you require.
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.