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.
Related
Is it possible to store value to attribute in class? If so then how?
For example:
class Student {
public $name;
public $grade;
function average() {
$sum = 0;
foreach ($this->grade as $key => $value) {
$sum += $value;
}
$avg = $sum/ count($key);
return $avg;
}
}
How to add values [math=8, history=9, biology=8] to attribute and develop method which count average of the grades?
You don't need to write any code in your class to assign values to $grade, because it's marked as public (see "Visibility" in the PHP documentation), which means code outside the class can access it.
After you create an instance of Student, you can just assign that array directly to the $grade property.
$student = new Student;
$student->grade = ['math'=> 8, 'history' => 9, 'biology'=> 8];
Instead, if you want to use that array as the default value for any new objects of this class, you can initialize the property to that value at the same time you declare it.
class Student {
public $name;
public $grade = ['math'=> 8, 'history' => 9, 'biology'=> 8];
// ...
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()
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
}
I want to load data to an instance of an object using its constructor and I write
$this->property=$row["colname"]
each time for each property.
the mysql_fetch_object function fetches the data as an object but I am not sure if the instance of an object can be assigned to some object from inside. othwerwise I would use
__construct($object) { $this=$object; } //doesn't give any syntax error
Maybe I should look into iteration of properties and use
foreach($object as $key => $value) $value=$object[$key];
or can I assign like
$this=$object;
within the constructor?
You can't assign anything to $this, or you'll get an error.
I would do something like this:
class SomeObject
{
function __construct($base = null)
{
if ($base != null)
{
$this->load($base);
}
// continue construction as you normally would
}
function load($object)
{
foreach ($object as $key => $value)
{
$this->$key = $value;
}
}
}
Then you have the option of load the array into the object at construction time, or after construction via load().
Usage example:
$rows = array('id' => 1, 'name' => 'Foo');
// create an empty SomeObject instance
$obj = new SomeObject();
var_dump($obj);
// load $rows into the object
$obj->load($rows);
var_dump($obj);
// create an instance of SomeObject based on $rows
$rows2 = array('id' => 2, 'name' => 'Bar');
$obj2 = new SomeObject($rows2);
var_dump($obj2);
Demo: http://codepad.org/uV7bOrfL
I'm making a class which needs to provide me with all the data from the MySQL-table "content".
I want to have my data returned as an object.
So far I managed to get one object returned, but i'd like to get an Object Collection with all my rows from the database returned.
<?
class ContentItem {
public $id;
public $title;
public $subtitle;
public $conent;
public $intro_length;
public $active;
public $start_date;
public $end_date;
public $views;
static function getContentItems() {
$query = "SELECT * FROM content";
$result = mysql_query($query)or die(mysql_error());
$item = new ContentItem();
while ($data = mysql_fetch_object($result)) {
$item = $data;
}
return $item;
}
}
For collections you need to create an object which implements Iterator interface. You can fill it with arrays, objects or whatever you want. Iterator makes sure you can use this collection in foreach loops after.
Furthermore, there's a mistake in your code. You are overwriting $item over and over again. You should create an array (or object with implemented Iterator, as I mentioned) which will be filled each cycle of while (as tandu wrote already).
Your loop keeps overwriting data with item, and new ContentItem() is overwritten immediately. If by "object collection" you mean "array," it's quite simple:
$items = array();
while ($data = mysql_fetch_object($result)) {
$items[] = $data;
}
return $items;
If you want to return your own custom object collection, then define the collection class and add $data to its collection each time (probably stored in an array as well).
The simple solution would be an array. I also assume you want a ContentItem made from each set of $data
$items = array();
while ($data = mysql_fetch_object($result)) {
$items[] = new ContentItem($data);
}
return $items;
If you later want to work with the items, you can use foreach
foreach ($items as $item) {
// do something with $item
}