Merge two PHP tags - php

I want to convert two different PHP tags into a single PHP tag.This may sound a little weird but recently I found a question like this and answer with correct marked.
I can't find I'm currently lost address.
My question:
for example;
$gates = array('t1','t2','t3',t4','t5');
$openGates-> and $gates merge.
Result:
$openGates->t1; or t2,t3.
If I remember correctly, the answer to the problem I found before was;
$openGates->{$gates}; like this. I not sure
How can I do that?

You seem to be confusing objects with arrays. Arrays simply contain data, unless you create them with keys also. Such as:
$gates = array('t1'=>true,'t2'=>false,'t3'=>"maybe",'t4'=>0,'t5'=>50);
Matthew Page is correct in that you should look up PHP OOP for a solution.
That being said, you can cast your array to an object providing it has both keys and values:
$gates = (object) array('t1'=>true,'t2'=>false,'t3'=>"maybe",'t4'=>0,'t5'=>50);
or
$openGates = (object) $gates;
This will allow you to access 'properties' of the object in the way you have demonstrated:
echo $openGates->t1;, for example. The -> operator only applies to objects, which are instances of classes, not arrays.
If you do cast your array to the type of object, be sure that you have both keys and values.

It's not simple for newbie programmer...
At first:
$gates = array('t1','t2','t3','t4','t5');
It's Array
$openGates->
This is class instance. Btw. You can retrieve class instance var like $className->varName
You can't simple merge array and class instance. But you can create new class instance variables by loop.
foreach($gates as $gateKey=>$gateVal) {
$openGates->$gatesVal = NULL;
}
But I think it's, in result should be like that:
$gates = array('t1'=>'opened','t2'=>'closed','t3'=>'closed','t4'=>'opened','t5'=>'opened');
foreach($gates as $gateKey=>$gateVal) {
$openGates->$gateKey = $gateVal;
}
echo $openGates->t1;
// or
foreach($gates as $key=>$val) {
echo $openGates->$key.PHP_EOL;
}
Btw you can simple set $openGates->gates = $gates; and call it like echo $openGates->gates['t1'];

Related

Is it necessary or useful to initialize sub-arrays in PHP?

Let's say I have a variable which is an initialized, empty array.
$cache = [];
The data in this array can be created like this, for example (please excuse the crude code and variable/key names, they're here for the sake of this example only):
for ($row in $someOtherArray) {
$cache[$row['id']][] = $row['data'];
}
Since $cache is a PHP array, I don't really need to initialize $cache[$row['id']] to also be an array. However, I sometimes encounter code like this:
for ($row in $someOtherArray) {
if (!isset($cache[$row['id']])) {
$cache[$row['id']] = [];
}
$cache[$row['id']][] = $row['data'];
}
Above, the sub-array is explicitly initialized as an empty array. Is it useful somehow? For example - does it help the interpreter in some way? Or is it only a developer being overzealous?
It's unnecessary as far as PHP is concerned. PHP will implicitly create any number of sub-arrays for you using the $foo[$bar][] syntax. It may be required for business logic, though not in this particular arrangement; it's simply redundant here. If the value assignment is somehow separate logic, but you still want to ensure that at least an empty array exists for the key, that's the only time it makes sense.
Once you have initialised a variable as an array, you can use array specific methods on that variable. For example array_push(), array_map() etc..

PhpUnit: how to create examples of data structures for testing?

Say you have a method that receives an array as a parameter. That method does some manipulation with that array and then outputs a different array.
public function createArrayForX(array $myArray){
return $modifiedArray;
}
In order for me to test that the output has some values I need to create some sample cases for my input. It is a tedious work to create arrays manually, especially big ones.
public function testCreateArrayForX(){
$myArray = []; // **how do I easily create myArray here**
$this->assertContains("String that I want", $this->sampleClass->createArrayForX($myArray));
}
I tried something like var_dumping my array in the program, copying the result from var_dump and transforming it back to array (Convert var_dump of array back to array variable) and then edit it to make different tests. Is there a simple way or am I doing things wrong if I need this?
So my question is how do you easily create a skeleton for you sample input that you can then change to test different scenarios?
print(var_export($myArray, true));
in the program gave me what I need.

How to access a two-level objected using variables?

Example objects:
$this->obj1->lvl1
$this->obj1->lvl1->lvl2
I know I can access objects like this:
$var = 'obj1';
$this->{$var}
But I want to go further. The problem is that it needs to be dynamic so the name needs to come from a string. I'm using this for mapping. So a user can use dot notations to access anything in the object. So if the user uses this notation:
'obj1.lvl1'
'obj.lvl1.lvl2'
So all I have to do is:
$this->obj1->{$mapped_string}
So $mapped_string can go either one level or two or more levels deep.
It will map directly to the object. Anyone know how I can accomplish this?
Split the string into accessors, and then drill down in a loop. This works for any length of accessors:
$obj = $this;
$accessors = explode('.', $mapped_string);
foreach ($accessors as $acc) {
$obj = $obj->{$acc};
}
var_dump($obj);

php - multi-dimensional array wrapper class

I have some data represented as multi-dimensional arrays. I would like to embed these data into my OO application and provide extra functionality to these data but also a way to access it both with the traditional random access and using an iterator (so I could use foreach). In other words I would like to implement a wrapping class for a multi-dimensional array.
What I already tried:
I. ArrayAccess
The problem with this one is that the server uses PHP 5.2.17 and &offsetGet() gives an error, thus I can't return by reference, which means I can't implement multidimensional element access:
$obj[$key1][$key2] = $value;
Note, that upgrading to a newer PHP version is currently not an option
II. Using magic methods
This is a bit trickier, but my problems rose when I tried using a variable as key. E.g.
$obj->$key1[$key2] = $value;
The interpreter first evaluated $key1[$key2] throwing a notice and returning the first char of $key1, and uses that as key on my array. I don't know how to solve this one either. I thought of using brackets to force operation priority, but that had the same problem as in my next attempt:
III. Using simple get and set functions
Again, old PHP. It cries when I try to write:
$obj->get($key1)[$key2] = $value;
Because it doesn't know how to index an expression ending in round brackets.
There's still the lost resort option: make the array public and forget OO all together. But before I go there I want to be certain that there's just really no other way of doing this.
Sometimes, it's best shown with an example. For instance, you could have a multidimensional array with ordered quantities of a product, where the first index defines a customer, the second an order and the third the products. The value then is the quantity.
IV. Using simple get and set functions, but with multiple parameters:
$value = $obj->get($key1, $key2);
$obj->set($key1, $key2, $value);
or
$quantity = $orderedQuantities($customerName, $orderNo, $productCode);
The essence of writing an object wrapper, is that it looks like an object and behaves like such. If you implement it so that it looks and behaves like an array, you may just as well use an array. The only reason to wrap an array in an object that behaves like an array is that you can pass it around by reference, without using & parameters.
If that is your goal, just assign the array to $obj, and use $obj->arrayprop[$key1][$key2]. If on the other hand you want it to behave like an object, skip the array syntax altogether.
V. Using nested objects
So using the same example, you can write a customers object (kind of a collection), which embeds order objects, etc..
$quantity = $customers->getCustomerByName($customerName)->getOrder($orderNo)->getProduct($productCode)->quantity;
or, to make it more readable:
$customer = $customers->getCustomerByName($customerName);
$order = $customer->getOrder($orderNo);
$orderLine= $order->getOrderLine($productCode);
$quantity = $product->quantity;
Now, each of these entities are represented by an object. The advantage is that you can easily extend this structure with extra properties. You can give the customer collection 'findByCustomerNo' and 'findByName' methods to find a specific customer, but also a 'filterByPostalCode', which could return a new collection containing only the customers from that postal code.
$order could now contain functions to calculate totals.
$orderLine may contain only a productCode (key) and a quantity, but by making it an object, you can easily add discount, a customized name or description or other properties.
All in all, this structure allows a lot of flexibility, although it needs a little more typing at first and a little getting used to.
Using nested objects can make ArrayAccess work, without passing references. But you can forget about built in array functions completely.
<?php
class ArrObj implements ArrayAccess {
private $arr;
public function __construct($arr = null) {
$this->arr = $arr;
}
public function offsetExists($key) {
return isset($this->arr[$key]);
}
public function offsetGet($key) {
return $this->arr[$key];
}
public function offsetSet($key, $val) {
return $this->arr[$key] = $val;
}
public function offsetUnset($key) {
unset($this->arr[$key]);
}
}
$a = new ArrObj(array(
'foo' => new ArrObj(array(
'bar' => 'qwe'
))
));
echo $a['foo']['bar'] . '<br />';
$a['foo']['bar'] = 'asd';
echo $a['foo']['bar'] . '<br />';
?>
Outputs:
qwe
asd

Using an Array as the Key for an Array in PHP

I need to create an association between an Array and a Number; as PHP lacks a Map type, I am trying using an array to achieve this:
$rowNumberbyRow = array();
$rowNumberByRow[$rowData] = $rowNumber;
However, when I evaluate the code, I get the following Error:
Warning: Illegal offset type
Just to note, the data stored in the array ($rowData) does not have any 'unique' values that I can use as a key for the $rowNumberByRow Array.
Thanks!
UPDATE:
To answer some of my commenters, I am trying to create a lookup table so that my application can find the row number for a given row in O(1) time.
PHP does have a map Class: It's called SplObjectStorage. It can be accessed with exactly the same syntax as a general array is (see Example #2 on the reference).
But to use the class you will have to use the ArrayObject class instead of arrays. It is handled exactly the same way arrays are and you can construct instances from arrays (e.g. $arrayObject = new ArrayObject($array)).
If you don't want to use those classes, you can also just create a function that creates unique hash-strings for your indexes. For example:
function myHash($array){
return implode('|',$array);
}
$rowNumberByRow[myHash($array)] = $rowNumber;
You will of course have to make sure that your hashes are indeed unique, and I would strongly suggest you use the SplObjectStorage and maybe read a little bit more about the SPL classes of php.
Why not just store the row number in the array? e.g:
$rowData['rowNumber'] = $rowNumber;
You could instead serialize the array, e.g:
$rowNumberByRow[serialize($rowData)] = $rowNumber;
However that's pretty inefficient.
In php you can use only scalar values as an array keys.
If your $rowNumber is unique - then you'd try to use the opposite relation direction. If it is not unique - then you don't have any possible solution I know.
The answer has been alredy given and accepted, but while i was searching for a similar problem, i found this question, and i felt like i should drop a line: when someone wants to use an array with values as keys for another array, it would be useful to use the function array_combine.
If i got the arrays correctly, you could use:
$rowNumberByRow = array_combine($rowData, $rowNumber);
Please take a look at the PHP manual to see some info about permitted values for the keys :)

Categories