i have a model extended from CActiveRecord
let says the name of the class is SomeModel and the object is $foo
$foo = SomeModel::model()->findByPk(1);
Then i created virtual attributes on that model
$foo->setImage('testing.jpg');
When i testing call the property/state it works perfectly:
var_dump($foo->image); // output testing.jpg
But when i do iteration with the model it didn't show the property.
foreach($foo as $key => $value) {
echo $key .' = '. $value."\n";
}
How to make the image property listed when i do iteration?
You can't iterate a model like that. Try this instead:
foreach ( $foo->getAttributes() as $key => $value ) {
// Do stuff
}
Related
I see in laravel for example, when looping through eloquent model it loops only through table attributes. For example
$user = new User(1);
foreach($user as $key => $value){
echo $key.' = '.$value.'<br>';
}
the output will be like this
id=1
first_name=jone
It loops only through table columns although the class has other attributes
My class is like this
class Model {
protected $prop1;
protected $prop2;
protected $columns = ['id' => 1, 'name' => 'name'];
}
I wanna implement something like that, so when I create an object and loop through it, only loop through $columns propery for example
$model = new Model();
foreach($model as $key => $value){
echo $key.' = '.$value.'<br>';
}
i need the output to be like this
id=1
name=name
You can define how php will treat you objects in a foreach loop.
See here for the documentation: http://php.net/manual/en/language.oop5.iterations.php
By default php will iterate over all public properties.
I have an object that implements Iterator and holds 2 arrays: "entries" and "pages". Whenever I loop through this object, I want to modify the entries array but I get the error An iterator cannot be used with foreach by reference which I see started in PHP 5.2.
My question is, how can I use the Iterator class to change the value of the looped object while using foreach on it?
My code:
//$flavors = instance of this class:
class PaginatedResultSet implements \Iterator {
private $position = 0;
public $entries = array();
public $pages = array();
//...Iterator methods...
}
//looping
//throws error here
foreach ($flavors as &$flavor) {
$flavor = $flavor->stdClassForApi();
}
The reason for this is that sometimes $flavors will not be an instance of my class and instead will just be a simple array. I want to be able to modify this array easily regardless of the type it is.
I just tried creating an iterator which used:
public function ¤t() {
$element = &$this->array[$this->position];
return $element;
}
But that still did not work.
The best I can recommend is that you implement \ArrayAccess, which will allow you to do this:
foreach ($flavors as $key => $flavor) {
$flavors[$key] = $flavor->stdClassForApi();
}
Using generators:
Updating based on Marks comment on generators, the following will allow you to iterate over the results without needing to implement \Iterator or \ArrayAccess.
class PaginatedResultSet {
public $entries = array();
public function &iterate()
{
foreach ($this->entries as &$v) {
yield $v;
}
}
}
$flavors = new PaginatedResultSet(/* args */);
foreach ($flavors->iterate() as &$flavor) {
$flavor = $flavor->stdClassForApi();
}
This is a feature available in PHP 5.5.
Expanding upon Flosculus' solution, if you don't want to reference the key each time you use the iterated variable, you can assign a reference to it to a new variable in the first line of your foreach.
foreach ($flavors as $key => $f) {
$flavor = &$flavors[$key];
$flavor = $flavor->stdClassForApi();
}
This is functionally identical to using the key on the base object, but helps keep code tidy, and variable names short... If you're into that kind of thing.
If you implemented the iterator functions in your calss, I would suggest to add another method to the class "setCurrent()":
//$flavors = instance of this class:
class PaginatedResultSet implements \Iterator {
private $position = 0;
public $entries = array();
public $pages = array();
/* --- Iterator methods block --- */
private $current;
public function setCurrent($value){
$this->current = $value;
}
public function current(){
return $this->current;
}
//...Other Iterator methods...
}
Then you can just use this function inside the foreach loop:
foreach ($flavors as $flavor) {
$newFlavor = makeNewFlavorFromOldOne($flavor)
$flavors -> setCurrent($newFlavor);
}
If you need this function in other classes, you can also define a new iterator and extend the Iterator interface to contain setCurrent()
Hi I want to know what am I doing wrong, and how can I save class variables into file.
class x{
public $xy=0;
function saveConfig($src){
$classArray = get_class_vars(get_class($this));
$line='';
foreach ($classArray as $k => $v) {
if(is_array($v)){
$line.=$k.'='.implode('|',$v)."\r\n";
}else if(isset($v)) $line.=$k.'='.$v."\r\n";
}
file_put_contents($src,$line);
echo $line;//test
return true;
}
}
This is test class. When running:
$test=new x;
$test->xy=5;
$test->saveConfig('testSrc.txt');
I'll get output "xy=0", but I want it to save/echo changed variable, that's mean "xy=5".
What is wrong with this code, why and how can I correct it ?
Change get_class_vars(get_class($this)) to get_object_vars($this).
get_class_vars returns the default properties of a class. get_object_vars returns the current properties of an object (an instance of a class).
I have an Abstract class that is extended by a child class.
I need to retrieve an array of all the properties and their values for the abstract class, from within a method inside the abstract class.
Is there a simpler way to do this other than this code:
$options = get_object_vars($this);
foreach ($options as $var => $value) {
if (!property_exists(get_class(), $var)) {
unset($options[$var]);
}
}
get_object_vars($this) returns all the properties and their values, but includes the properties of the child class - which I don't want.
$options = get_class_vars(get_class());
foreach($options as $key=>$val)
echo $key . " : " . $val . " => " . $this->$key;
This will give an output as
Propertyname : standardvalue => dynamic value
I am currently in the development of my Class in PHP.
I have an array with values in it, and I would like to use the array fieldname as a $this reference. Let me show you what I got:
<?php
class Server {
private $playlist;
private $mp3;
private static $ressourceFolder;
private static $sudoUser;
And in my array it contains:
array(6) {
["playlist"]=>
int(8002)
["mp3"]=>
int(1024)
["ressourceFolder"]=>
bool(true)
["sudoUser"]=>
bool(true)
}
So I would like to use in my foreach something to get the value of the array field into the class global variable, the array fieldname is the same as the variable so this 'should' work, but it doesn't :(
foreach($ressourceArray as $ressourceField=>$ressourceValue) {
$this->$ressourceField = $ressourceValue;
}
I would really appreciate if someone could tell me why this can't work and how to make this 'workable'...
Thanks in advance!
It does work, see Demo:
<?php
$array = array("playlist"=> 8002, "mp3"=>1024);
class Mix {
public function __construct($array) {
foreach($array as $key => $value) {
$this->$key = $value;
}
}
}
$class = new Mix($array);
var_dump($class);
It will assign new public members to the object $this based on key/value pairs of the array.
Dealing with bad named keys in the array
If the keys contain values that are not valid variable names, it can be non-trivial to access the properties later ({property-name}), see PHP curly brace syntax for member variable.
Casting the array to object before adding will help to prevent fatal errors for those key names that are completely invalid:
$object = (object) $array;
# iterate over object instead of array:
foreach($object as $key => $value) {
$this->$key = $value;
}
Those keys are just dropped by the cast.
You may get it working with the magic method __set and __get. See: http://php.net/manual/en/language.oop5.magic.php
And in my array it contains:
What array? That looks like a array dump of an instance of the class.
into the class global variable
What global class variable? Classes are not variables. Variables may hold references to objects, or class names.
Assuming you want to iterate through the properties of an object, and
$ressourceArray = new Server();
The code will work as expected.
If the loop is within a class method, then the loop should be....
foreach($this as $ressourceField=>$ressourceValue) {
$this->$ressourceField = $ressourceValue;
}
If you mean that you are trying to initialize the object properties from an array...
class Server {
...
function setValues($ressourceArray)
{
foreach($ressourceArray as $ressourceField=>$ressourceValue) {
$this->$ressourceField = $ressourceValue;
}
}
(BTW there's only one 's' in 'resource')