I have a class with several variables like:
class ABC
{
$var1=0;
$var2=0;
...
}
Instead of setting variables one by one like;
$ABC=new ABC();
$ABC->var1=1;
$ABC->var2=1;
...
How to loop through all class' (instance) variables and dynamically set them all to some value.
You could use get_object_vars to get the non static properties of the object, and then loop through that.
$object_vars = get_object_vars($ABC);
foreach ($object_vars as $name => $value) {
$ABC->{$name} = $newVal;
}
See more information here: http://php.net/manual/en/function.get-object-vars.php
Related
class UpcomingEvents {
//Variable I'm trying to make accessible and modify throughout the class methods
private static $postObjArr = array();
private static $postIdArr = array();
private static $pinnedPost;
//My attempt at a get method to solve this issue, it did not
private static function getPostObjArr() {
$postObjArr = static::$postObjArr;
return $postObjArr;
}
private static function sortByDateProp($a, $b) {
$Adate = strtotime(get_field('event_date',$a->ID));
$Bdate = strtotime(get_field('event_date',$b->ID));
if ($Adate == $Bdate) {
return 0;
}
return ($Adate < $Bdate) ? -1 : 1;
}
private static function queryDatesAndSort($args) {
$postQuery = new WP_Query( $args );
if( $postQuery->have_posts() ) {
while( $postQuery->have_posts() ) {
$postQuery->the_post();
//Trying to push to the array, to no avail
array_push(static::getPostObjArr(), get_post());
}
}
//Trying to return the array after pushing to it, comes back empty
return(var_dump(static::getPostObjArr()));
//Trying to sort it
usort(static::getPostObjArr(), array(self,'sortByDateProp'));
foreach (static::getPostObjArr() as $key => $value) {
array_push(static::$postIdArr, $value->ID);
}
}
}
I'm trying to access $postObjArr within the class, and push to it with the queryDatesAndSort(); method. I've tried a couple of things, most recent being to use a get method for the variable. I don't want to make it global as it's bad practice I've heard. I've also tried passing by reference I.E
&static::$postObjArr;
But when it hits the vardump, it spits out an empty array. What would be the solution and best practice here? To allow the class methods to access and modify a single static array variable.
static::$postObjArr[] = get_post()
I didn't think it would of made a difference, but it worked. Can you explain to me why that worked but array.push(); Did not?
Arrays are always copy-on-write in PHP. If you assign an array to another variable, pass it into a function, or return it from a function, it's for all intents and purposes a different, new array. Modifying it does not modify the "original" array. If you want to pass an array around and continue to modify the original array, you'll have to use pass-by-reference everywhere. Meaning you will have to add a & everywhere you assign it to a different variable, pass it into a function, or return it from a function. If you forget your & anywhere, the reference is broken.
Since that's rather annoying to work with, you rarely use references in PHP and you either modify your arrays directly (static::$postObjArr), or you use objects (stdClass or a custom class) instead which can be passed around without breaking reference.
How do I know if an arbitrary object has any properties in PHP?
I need it for a recursive search on JSON objects as a break condition
i.e break search when the object has no more sub-objects.
I thought of property_exists but it checks a particular property, while I want to know if any property exists.
You can use a foreach loop:
foreach (new object as $prop => $value) {
echo "property \$$prop is $value\n";
}
Also You can do it conveniently with get_object_vars:
$propertyName = key(get_object_vars($object));
The function get_object_vars() will return a list of all accessible properties on an object.
You can try to use this function:
http://php.net/manual/en/function.get-object-vars.php
From the docs:
Returns an associative array of defined object accessible non-static properties for the specified object in scope. If a property has not been assigned a value, it will be returned with a NULL value.
You can also use the ReflectionClass to get the object properties like this:
$obj = new YourObjectClass;
$reflect = new ReflectionClass($obj);
$props = $reflect->getProperties();
foreach ($props as $prop) {
print $prop->getName() . "\n";
Casting the object to an array and performing a count on the resulting array will tell you if an object has properties.
$foo = new Bah();
$propertiesAsArray = (array) $foo;
if(count($propertiesAsArray)) {
//this object has properties
} else {
//this object does not have properties
}
You could use :
if(isset($yourobject)){
//YourCode
}
in a loop to see if the object have anything already set.
I have trouble dynamically declaring variables inside a class/object in PHP.
I have a class called Column and it receives an associative array of (names => values) of an unknown length.
I need the class variables to have the exact same name as in the array (and their values to match obviously).
Since Variable Variables method is a bit confusing, when you add on top of it the class/object declaration syntax, I feel I lost myself in it a bit.
I tried something like this:
function __construct($array)
{
foreach ($array as $key => $value)
{
$this->$key;
$this->key=$value;
}
}
i would usually not do this
$this->$key;
I thought $this->key would fit the syntax,but apparently I was wrong. If someone could help correct me it would very helpful.
Just use the {} syntax:
function __construct($array)
{
foreach ($array as $key => $value)
{
$this->{$key} = $value;
}
}
Instead of
$this->$key;
$this->key=$value;
It should be
$this->$key=$value;
What's the difference?
The variable property $this->$key; as single statement accesses the property with the name in $key but does not do anything with it. But it will trigger a notice Undefined property if the property has not been declared or dynamically assigned before.
$this->key accesses the literal key property, that is public $key; if it has been declared explicitly.
$this->$key accesses the property with the name stored in $key. So if $key === 'foo' it is the same as $this->foo.
Assigning properties dynamically that have not been declared before is independent of using variable properties. So if the property $foo does not exist, $this->foo = 1 is the same as $this->$key = 1 with $key === 'foo'. Both create a public property $foo on the current object.
Special cases
If $key is not a string, it will be casted to string. If it is an object or resource that cannot be casted to string, you will get a could not be converted to string error.
If $key converts to an empty string, you will get a Cannot access empty property error.
If $key starts with a number or contains special characters that are usually not allowed in variable names (like $), the property will be created anyway. Accessing properties with names like this is always possible if you use {} to use arbitrary expressions as property names. Try this:
$o = new stdclass;
$o->{'!"§$%'} = 'it works';
echo $o->{'!"§$%'};
I create my mini-micro framework. In my class which loads template I have property named $variable. This property stores array of viariables which should be available in my template.
For example:
$this->variable = array($key=>5, $data=>10);
Next, I use function extract()
extract($this->variable);
So, now in my template(test.html.php) I have simple access to passed variables:
test.html.php
echo $key;
I also have method named import().
In my template I have access for this method by operator $this
test.html.php
$this->import();
Is there any possibility to call my function import() in template, without operator $this?
Have your template implement the __invoke() magic method.
class Template {
......
public function __invoke() {
$this->import();
}
}
Set a variable named import which is equal to $this.
$this->variable['import'] = $this;
When you extract the variables a variable named $import will be available and if you do $import() in the template it should call the __invoke() method of the template class which in turn calls the import() method of the class.
You should try and refrain from calling methods in templates though if possible. You should just be dealing with variables. A little call to $import() somewhere in there may not be the worst thing in the world, it depends what that method is doing.
If you can, please try to avoid using extract() and the global scope.
be careful, when using extract()
extract() is a very dynamic language feature, which tends to cause clashes with variables already existing in the local scope. You have to take care of that by using the second
parameter, which controls the newly created variables.
(EXTR_SKIP) including not overwriting any existing variables ,
(EXTR_IF_EXISTS) ONLY overwriting existing variables (so you can create a whitelist)
(EXTR_PREFIX_ALL) or by adding prefixes to the variables
extract() causes developer confusion, because new developers on your project, simply don't grasp were variables are coming from.
extract() is also a performance killer, in regards to using it with HHVM, because of the extra book-keeping of scoped-variables, which needs to be done. In short: avoid it, when optimizing for speed on HHVM.
Still it's common practice to use extract in the View object, like so:
using extract() in a View object
// View.php
class View {
public $variables;
function render($filename) {
extract($this->variables);
ob_start();
$this->returned = include($this->dir . $this->filename);
return ob_get_clean();
}
}
// test.php
$view = new View;
$view->variables = array('test' => 'Hello World!');
$template = __DIR__.'/test.tpl';
echo $view->render($template);
// var_dump($view->returned); // to see included template content
// Template: test.tpl
<p><?php echo $test; ?></p>
If you really want to pollute the global scope:
Merge Variable to $GLOBALS
$GLOBALS += $vars;
function globalize($data) {
$GLOBALS += $data;
}
$vars = array('a' => 1, 'b' => 2);
globalize($vars);
echo $a; // prints 1
foreach with creating dynamic global variables from key names
foreach($array as $var_name => $var_value)
{
global $$var_name;
$$var_name = $var_value;
}
or better (to avoid clashes) directly add to GLOBALS array.
foreach($array as $var_name => $var_value)
{
$GLOBALS[$var_name] = $var_value;
}
Works, but is evil...
I need to initialize an array of objects in PHP.
Presently I have the following code:
$comment = array();
And when i am adding an element to the array
public function addComment($c){
array_push($this->comment,$c);
}
Here, $c is an object of class Comment.
But when I try to access an functions of that class using $comment, I get the following error:
Fatal error: Call to a member function
getCommentString() on a non-object
Can anyone tell me how to initialize an array of objects in php?
Thanks
Sharmi
$this->comment = array();
Looks like a scope problem to me.
If $comments is a member of a class, calling $comments inside a function of that class will not actually use the member, but rather use an instance of $comments belonging to the scope of the function.
If other words, if you are trying to use a class member, do $this->comments, not just $comments.
class foo
{
private $bar;
function add_to_bar($param)
{
// Adds to a $bar that exists solely inside this
// add_to_bar() function.
$bar[] = $param;
// Adds to a $bar variable that belongs to the
// class, not just the add_to_bar() function.
$this->bar[] = $param;
}
}
This code might help you:
$comments = array();
$comments[] = new ObjectName(); // adds first object to the array
$comments[] = new ObjectName(); // adds second object to the array
// To access the objects you need to use the index of the array
// So you can do this:
echo $comments[0]->getCommentString(); // first object
echo $comments[1]->getCommentString(); // second object
// or loop through them
foreach ($comments as $comment) {
echo $comment->getCommentString();
}
I think your problem is either how you are adding the objects to the array (what is $this->comment referencing to?) or you may be trying to call ->getCommentString() on the array and not on the actual objects in the array.
You can see what's in the array by passing it to print_r():
print_r($comment);
Presuming you have Comment objects in there, you should be able to reference them with $comment[0]->getCommentString().