Creating an array of objects in PHP - php

I would like to know what is the right of creating objects arrays in php.
My goal here is to be able to get data like this:
$obj = new MyClass();
echo $obj[0]->parameter; //value1
echo $obj[1]->parameter; //value2
Thanks for your time.
EDIT:
And if I want to do it in class it should look like this?
class MyClass{
public $property;
public function __construct() {
$this->property[] = new ProjectsList();
}
}

Any of the following are valid:
$myArray = array();
$myArray[] = new Object();
$myArray[1] = new Object();
array_push($myArray, new Object);

Try this,
$obj = array(new stdClass(), new stdClass())
or
$obj = array()
$obj[] = new stdClass()
$obj[] = new stdClass()
EDIT:
Class to stdClass

An important hint ...
The memory allocation for PHP arrays is exponential. A simple example: All array entries fit into an array, that allocates 2MB of memory. If this memory is no longer sufficient for all array entries, the memory allocation is expanded exponentially until the PHP memory limit is reached. If the array needs more than the 2 MB in this example, it will expand to 4MB, 16MB, etc.
When dealing with objects, better use collections. PHP provides the SplObjectStorage. This kind of collection allocates the exactly needed memory for its contents. Iteration over this collections behaves like using a yield. Only the memory for the current object in iteration is allocated. Beside that the SplObjectStorage class takes objects only. Should work perfectly for your purposes.
<?php
declare('strict_types=1');
namespace Marcel;
$collection = new SplObjectStorage();
$object1 = new stdClass();
$object2 = new stdClass();
$collection->attach($object1);
$collection->attach($object2);
The above shown code allows some stricter searching.
$collection->contains($object1); // returns true
Detaching an item works like a charme.
$collection->detach($object1);
$collection->contains($object1); // returns false
Iterations works with a pretty fast foreach loop or a while loop.
$collection->rewind();
foreach ($collection as $object) {
// yielding works here
}
$collection->rewind();
while ($collection->valid()) {
// yielding also works here automatically
$collection->next();
}

hope this will be helpful
$newArray[] = (object) array();

Honestly, I think you are on the right path. from what it sounds like you are not just trying to add to arrays, but convert arrays to objects.
<?php
$obj = (object) 'ciao';
echo $obj->scalar; // outputs 'ciao'
?>
PHP Objects
EDIT: I don't think you could add an object like this:
$this->property[] = new ProjectsList();
the "new ProjectsList()" would be how you would create an object from a class. ProjectsList would need to be a class. it would look more like this:
$obj = new ProjectsList;
$this->property[] = $obj;
you would need to make sure the ProjectsList existed first though.

Related

When is it appropriate to use an ArrayObject instead of an Array

I'm wondering when, if ever it would be appropriate to use an ArrayObject() instead of an Array()? Here's an example i've been working on.
To me i'm thinking a simple array will work, but i found ArrayObject() in the manual and I'm wondering, if it would be better to use one instead of a simple array.
public function calculateTotal(){
if(count($this->items) > 0){
$n = 0;
foreach($this->items as $item){
if($item->size == 'small'){
$k = $item->price->small;
}
if($item->size == 'large'){
$k = $item->price->large;
}
$n += $k * $item->quantity;
}
}else{
$n = 0;
}
return (int) $n;
}
Now I'm confused as to how i should construct the object.
for instance can i construct it with the short array syntax?
$this->items = []; //empty object
or should i construct is as an Array object
$this->items = new ArrayObject(); //empty object
I'm also confused as to how exactly i should push new items to the array.
i have the following function i'm writing:
Also how should i append arrray objects to this object?
is this good?
public function additem($item){
$add = [
'item_id'=>$this->item_id(),
'name'=>$item['name'],
'size',$item['size'],
'quantity'=>$item['quantity'],
'price'=>[
'large'=>$item['price'],
'small'=>$item['price']
]
]
array_push($this->items,$add);
}
or should i instead use ArrayObject::append() or some other method?
I checked the manual and it says this:
public void ArrayObject::append ( mixed $value )
Appends a new value as the last element.
Note:
This method cannot be called when the ArrayObject was constructed from an object. Use ArrayObject::offsetSet() instead.
source http://php.net/manual/en/arrayobject.append.php
The reason i'm asking this now is, later on when needing to delete items from this list how will i find what i'm looking for? can i use in_array() on this object.
I apologize in advance for these questions that might seem dumb to you, but keep in mind I'm still learning some of the more technical things. Thank you
There's nothing in your first snippet that would require ArrayObject. KISS and use simple arrays: array_push($this->items,$add); or $this->items []= $add; are both fine.
As a side note, there's a discrepancy between calculateTotal and add in your code: you have to decide whether you want your item structures to be arrays ($item['price']) or objects ($item->price). My advice is to use arrays, but that's really up to you.

Completely remove objects from runtime

I'm running a job where I import stock information from loads of suppliers. Some of them have many products, so when I store them in memory it quickly gets pretty heavy.
For that reason, I'd like to - after doing whatever-i-do-with-them - completely unset each supplier.
Each "supplier" is a Reader and a Processor which gets injected into a Manager which will return all data to N writers. The manager stores the Reader and Processor (which is the classes where the big amount of data will be) in a simple array.
Here's a quick demonstration:
$first = new stdClass();
$first->name = "I'm an object";
$first->age = 12;
$second = new stdClass();
$first->name = "I'm also an object!";
$first->age = 9;
$arr = array($first, $second);
while ($data = array_shift($arr)) {
echo "Emptying array one by one... \n";
//doesn't matter if you unset($data) or do $data=null;
}
//I want this to be empty, but's not
var_dump($first);
For now, I do a foreach() on the array and makes the value be passed by reference, which I then passes (by reference) to a cleanup() method. This feels clumsy.
Am I missing something obvious? How can I achieve this?

Creating an array in PHP

If I wanted to create an array in PHP with the following format, what would be the best way to approach it? Basically I want to declare the array beforehand, and then be able to add the values to person_id, name and age.
'person_id' => array('name'=>'jonah', 'age'=> 35)
To the first answer #Joe, first of all, your class doesn't support encapsulation since your attributes are public. Also, for someone who doesn't know how to create an array, this concept may be a bit complicated.
For the answer, changing a bit the class provided by #Joe, PHP provide a simple way of using arrays:
If you need many rows for this array, each row has a number, if not, remove the [0] for only one entry.
$persons = array();
$persons[0]['person_id'] = 1;
$persons[0]['name'] = 'John';
$persons[0]['age'] = '27';
Depending on how you want to use it, you could make a simple object:
class Person
{
public $person_id;
public $name;
public $age;
}
$person = new Person; // make the object beforehand
$person->person_id = 123; // their id
$person->name = 'Joe'; // my name
$person->age = 21; // yeah, right
This is virtually identical to an array (in terms of how it's used) except for:
Instead of new array() you use new Person (no brackets)
Instead of accessing items with ['item'] you use ->item
You can start with an empty array:
$arr = Array();
Then add stuff to that array:
$arr['person_id'] = Array();
$arr['person_id']['name'] = "jonah";
$arr['person_id']['age'] = 35;

Extra loop iteration happening when looping through array of objects

I made this object array
$trailheads[] = new StdClass;
Then I was putting an object in there each time it looped
$trailheads[] = $trailhead;
Then I returned the whole thing from the function like this:
$ret->ok = empty($errors);
$ret->errors = $errors;
$ret->o = $trailheads;
return $ret;
Once I got the values back, and loop through the results in the trailheads[] I keep looping 3 times instead of the expected 2. Is there a reason an extra iteration might be happening?
Here is how I try to loop:
foreach ($trailhead_list->o as $key)
{
$objkey = (object) $key;
echo '<p><h3>Trailhead Name: '.$objkey->trailhead_name.'</h3></p>';
}
After this:
$trailheads[] = new StdClass;
your $trailheads array contains on element, an instance of StdClass.
Then you add more elements, but there will be that first one.
Maybe you wanted to initialize the $trailheads[] like that, but instead you gave value to one of the array elements. Use this instead:
$trailheads = array();
This:
I made this object array
$trailheads[] = new StdClass;
... appears to be the source of the extra array element. Instantiate an array empty like this:
$trailheads = array();
Then loop and add objects:
$trailheads[] = $trailhead;
Also a note: I am guessing you don't have notices or warnings enabled. Turn them on while you develop. The line $trailheads[] = new StdClass; would have generated a notice, since you are adding a new element to a variable that hasn't been declared as an array (or anything else). PHP's loose typing is very forgiving, but this line would have generated a notice.
Warnings and notices on while you develop, turn them off for production. It will help you avoid common bugs and it will make you a better programmer to boot.
In the line:
$trailheads[] = new StdClass;
You are assigning a new StdClass object into the $trailheads array. That is to say you aren't declaring it as a variable but actually adding an element.

can i use stdClass like an array?

is it possible to make stdClass objects work like a generically indexed array?
i.e.
$array = Array
(
[0] => 120
[1] => 382
[2] => 552
[3] => 595
[4] => 616
)
would be constructed like
$a = array();
$array[] = 120;
$array[] = 382;
etc.
but if i do that with an object it just overwrites itself:
$obj = new stdClass;
$obj->a = 120;
$obj->a = 382;
i know i can change 'a' every time,
sorry if this is a stupid question but it's stumping me for some reason!
Appreciate any help :)
Dan
In short, no, because you will always have to name your properties. Going through the trouble of writing a simple class with ArrayAccess makes no sense either as you've essentially recreated an array with nothing to show for it except extreme sacrifices in performance and transparency.
Is there some reason your problem cannot be solved infinitely more simply by using an array, or is this just a wish-I-knew question?
EDIT: Check out this question for more info.
No, you can't. Using the brackets ([]) like that is called "ArrayAccess" in PHP, and is not implemented on the stdClass object.
It sounds like you might want something like
$foo = new stdClass();
$foo->items = array();
$foo->items[] = 'abc';
$foo->items[] = '123';
$foo->items[] = 'you and me';
You could also try casting an array as a stdClass to see what happens.
$foo = array();
$foo[] = 'abc';
$foo[] = '123';
$foo[] = 'you and me';
$foo = (object) $foo;
var_dump($foo);
I can't really see what you mean to do, short of
<?php
$obj->a = array();
$obj->a[] = 120;
$obj->a[] = 382;
// ...
?>
You cannot simply "push" a field onto an object. You need to know the name of the field in order to retrieve the value anyways, so it's pretty much nonsense.
An object is not an array. If you want numerically indexed elements, use an array.
If you want named elements use either an Object or an Associative Array.
As for why you're getting different behaviour, it's because in the Array, you are not specifying an index, so PHP uses the length of the Array as the index. With the Object, you have to specify the name (in this case 'a').
The other thing you may want to do is have an Object, with a member that is an array:
$obj = new stdClass;
$obj->arr = array();
$obj->arr[] = 'foo';
$obj->arr[] = 'bar';
also don't forget you can cast an array to an object:
$obj = (object) array(
'arr' => array(
'foo',
'bar'
)
);
Only for the sake of OOP, don't use classes. If you really want to implement this functionality, use this class:
class ArrayClass
{
protected $storage = array();
public function push($content) {
$this->storage[] = $content;
return $this;
}
public function get($index) {
if (isset($this->storage[$index])) {
return $this->storage[$index];
} else {
//throw an error or
return false;
}
}
}
You can get exactly this in JavaScript.

Categories