i have an array in php full of "Eventos Calendario" objects, at some point in my script i need to introduce a new object of the same type at position x of this array. this is the code i am using
$EventoLimite = new EventosCalendario(null,$Timestamp, $TipoEvento);
var_dump($EventoLimite);
array_splice($this->EventosEntrada, $i, 0, $EventoLimite); //
var_dump($this->EventosEntrada[$i]);
And the "Var_Dumps" i am getting are:
object(EventosCalendario)[15]
public 'FechaHora' => int 1376334000
public 'FechaHoraOriginal' => null
public 'Tipo' => string 'Entrada' (length=7)
public 'Origen' => string 'Insertado' (length=9)
public 'Subtipo' => null
public 'ID' => null
int 1376334000
Why is the new slot in the array only getting the value of "FechaHora" property? i need to get the whole object in $this->EventosEntrada[$i]. how can i do that??
The "replacement" argument must be an array itself, so you should write
array_splice($this->EventosEntrada, $i, 0, [$EventoLimite]); // note []s
maybe its because of that when you introduce a new object, just public variables and functions are available in the specific file you work on. I mean it is cause by access of clsasses.
Related
I do have an array of objects retrieved from DB with PDO fetchALL(PDO::FETCH_OBJ). When I var_dump first element of that array:
var_dump($this->stockList[0]);
I get:
object(stdClass)[5]
public 'userId' => string '3' (length=1)
public 'symbol' => string 'ibm' (length=3)
public 'date' => string '2019-01-03' (length=10)
public 'quantity' => string '5' (length=1)
public 'bought' => string '1' (length=1)
public 'observed' => string '0' (length=1)
public 'dividendRate' => string '6.28' (length=4)
public 'exDividendDate' => string '2018-11-08' (length=10)
public 'forwardDividend' => string '31.400000000000002' (length=18)
I would like to use reflection on this object to get all of it's properties:
$r = new ReflectionClass($this->stockList[0]);
$objProperties = $r->getProperties();
I get proper class:
var_dump($r);
produces:object(ReflectionClass)[16]
public 'name' => string 'stdClass' (length=8)
but I can't get properties of that object:
var_dump($objProperties);
gives an empty array:
array (size=0)
empty
So, the question is how do I get a list of properties of that object?
My full code:
$sql = "query";
$this->stockList = $this->con->query($sql)->fetchAll(PDO::FETCH_OBJ);
var_dump($this->stockList[0]);
$r = new ReflectionClass($this->stockList[0]);
$objProperties = $r->getProperties();
var_dump($r);
var_dump($objProperties);
Reflection with an StdClass will not work. The call to ReflectionClass(), parameter one uses the ::class of the instance to determine its properties. Since StdClass has no properties at default and are given dynamically, Reflection can not find any properties since by default they do no exist.
You can see the above in a demo. However, for even more simplicity, this would work fine:
var_dump(array_keys((array) new Foo('bar'))); # Based on above demo
However, do not panic. You do not need to use reflection to do this: \PDO::FETCH_ASSOC will give you a multidimensional array. You can use array_keys() to get the parameters. Then, later, if you prefer to use the result as an object, cast the array as an object.
# Fetch Query
$this->stockList = $this->con->query($sql)->fetchAll(PDO::FETCH_ASSOC);
# Get properties which will be, in this case, ['id', 'symbol', 'date', 'quantity', 'bought', 'observed', 'dividendRate', 'exDividentDate', 'forwardDivident']
$properties = array_keys($this->stockList[0]);
# Revert all back to StdClass instances by casting the array to object
foreach($this->stockList as &$stockItem) {
$stockItem = (object) $stockItem;
}
Alternativly, as suggested in the comments by #Quasimodosclone. You can use get_object_vars() which will return the array equivalent of the object. Then, like before, use array_keys() to get the properties.
$this->stockList = $this->con->query($sql)->fetchAll(PDO::FETCH_OBJ);
$properties = array_keys(get_object_vars($this->stockList[0]));
After testing this out of curiosity, the object can be casted to an array to achieve more simplicity.
$this->stockList = $this->con->query($sql)->fetchAll(PDO::FETCH_OBJ);
$properties = array_keys( (array) $this->stockList[0] );
Currently I'm looping through a quite large data set. This multidimensional array needs to be grouped by specific array values of its sub arrays. As this is a holiday project, I want to do deepen my knowledge and make more use of PHPs Iterators. Point is, that I don't know how to transform a numeric multi-dimensional Array into a multi-dimensional array with associative keys.
Shortened example (GeoJSON to Array)
array (size=4)
'type' => string 'FeatureCollection' (length=17)
'features' => // THIS is the actual array
array (size=207)
0 => // Sub-Arrays like this one are repeating
array (size=5)
'type' => string 'Feature' (length=7)
'geometry' =>
array (size=2)
'type' => string 'LineString' (length=10)
'coordinates' =>
array (size=410)
0 =>
array (size=2)
0 => float 16.359980888872
1 => float 48.208437070943
// etc.
'geometry_name' => string 'SHAPE' (length=5)
'properties' =>
array (size=5)
'OBJECTID' => int 273
// This/"LBEZEICHNUNG" is the part I want to order/summon
// all further "geometry"-parts by
'LBEZEICHNUNG' => string '13A, 2, 86, U3' (length=1)
'LTYP' => string '1' (length=1)
'LTYPTXT' => string 'Tramway' (length=12)
'SE_ANNO_CAD_DATA' => null
'id' => int 1
The features array is what holds the actually looped datasets. And LBEZEICHNUNG are the values (single or comma separated) I want to sort/order by.
To make an example:
// Original values:
'LBEZEICHNUNG' => string '13A, 2, 86, U3'
// Now split them and push the features into new keys that have those values:
'13A' => array(
0 => // Sub-Arrays like this one are repeating
array (size=5)
'type' => string 'Feature' (length=7)
'geometry' =>
array (size=2)
'type' => string 'LineString' (length=10)
'coordinates' =>
array (size=410)
0 =>
array (size=2)
0 => float 16.359980888872
1 => float 48.208437070943
// etc.
'geometry_name' => string 'SHAPE' (length=5)
'properties' =>
array (size=5)
// "OBJECTID" now is obsolete
// "LBEZEICHNUNG" is now obsolete
'LTYP' => string '1' (length=1)
'LTYPTXT' => string 'Tramway' (length=12)
'SE_ANNO_CAD_DATA' => null
// "id" now is obsolete as well
),
"2" => // gets the same values as "13A"
// same goes for "86" and "U3"
Now every sub array that would have either 13A, 2, 86 or U3 in ["properties"]["LBEZEICHNUNG"], would push its geometry to the end of the already existing subarray/sub-Iterator.
So far I only got a basic recursive Iterator set up, that runs through all leaves.
$data = new \RecursiveArrayIterator( $fileContents );
foreach( new \RecursiveIteratorIterator( $data ) as $key => $value )
{
// foo. bar. dragons.
}
Point is that I can't really figure out how to assign new keys from values in the Iterator. I already tried using a RecursiveFilterIterator and failed gracefully as its simply not intended to do this. Quite frankly: I'm lost as I either can't find the right Iterator to use or I simply ain't know enough about Iterators yet.
I got a working solution with nested foreach-es pushing into another Array. As this is my holiday project I want to learn, hence the Iterator solution, which I hope is more maintainable in the long turn.
Edit: Link to the original Geo-JSON data set CC-BY-SA 3.0/AUT - Data provided by the City of Vienna. Other formats can be found here.
If I understood correctly, you want to sort/ or group the array based on that "LBEZEICHNUNG" key, and use PHP iterators. In order to do that, you have to traverse the entire array, and build a new one that holds the values grouped by that key. This is simple foreach logic.
Iterators shine when you want to traverse a data collection and fetch the data during traversal (or alter it).
In this case, you are fetching the data outside of the iterator (json_decode ?), so that makes iterators kind of pointless - unless you need to do more than just sorting. If you do, I'd suggest you store that data in a format that allows you to easily fetch sorted sets, like a database, then you can use iterators to their full potential.
One way to group the routes is to use basic OOP:
class Route{
protected $trams = array();
// add other route properties (type, geometry etc.)
public function assignTo(Tram $line){
if(!in_array($line, $this->trams, true))
$this->trams[] = $line;
}
public function getTrams(){
return $this->trams;
}
}
class Tram{
public $name;
protected $routes = array();
public function __construct($name){
$this->name= $name;
}
public function addRoute(Route $route){
$this->routes[] = $route;
$route->assignTo($this);
}
public function getRoutes(){
return $this->routes;
}
}
Example:
$trams = array();
foreach($data as $routeData){
$route = new Route();
$tramNames = explode(', ', $routeData['features']['properties']['LBEZEICHNUNG']);
foreach($tramNames as $name){
if(!isset($trams[$name]))
$trams[$name] = new Tram($name);
$trams[$name]->addRoute($route);
// set other route properties...
}
}
You can use usort to sort your multi-dimensional array based on sub-values:
$JSON = iconv('UTF-8', 'UTF-8//IGNORE', utf8_encode(file_get_contents("http://data.wien.gv.at/daten/geoserver/ows?service=WFS&request=GetFeature&version=1.1.0&srsName=EPSG:4326&outputFormat=json&typeName=ogdwien:OEFFLINIENOGD")));
$geoarray = json_decode($JSON, true);
$myarray = $geoarray["features"];
function cmp($a, $b) {
return $a["properties"]["LBEZEICHNUNG"] - $b["properties"]["LBEZEICHNUNG"];
}
usort($myarray, "cmp");
print_r($myarray);
My situation is quite simple, but i'm still looking for a nice and short solution for it.
Here is my case:
I receive a soap response object which is my be different from a call to another.
Sometimes, these properties are objects themselves and may have properties we have to get. For this, an array is set for each type of call to select the data wanted and discard the rest.
By example, in a call we receive an object like this:
(I made a code easy to test by mocking the received object)
$objTest = new stdClass();
$objTest->Content1 = "";
$objTest->Content2 = new stdClass();
$objTest->Content2->prop1=1;
$objTest->Content2->prop2=2;
$objTest->Content2->prop3=3;
$objTest->Content3 = 3;
$objTest->Content4 = array('itm1'=>1, 'itm2'=>'two');
i want to check if $objTest->Content2->prop3 exist, but i don't know at the right moment i am looking for this because what i'm looking for is in the associative array.
The array for the call look like:
$map = array('Content3','Content2->prop3');
From now i am able to get the content of the Content3 property by doing this:
foreach ($map as $name => $value) {
if (isset($object->$name)) {
echo "$value: ". json_encode($object->$name)."\n";
}
}
But not for the other because of the reference "->".
Now my question:
Is there a way to get an unknown property of an unknown object as displayed above?
This is a result of the previous test:
Dump of objTests:
object(stdClass)[1]
public 'Content1' => string '' (length=0)
public 'Content2' => object(stdClass)[2]
public 'prop1' => int 1
public 'prop2' => int 2
public 'prop3' => int 3
public 'Content3' => int 3
public 'Content4' => array (size=2)
'itm1' => int 1
'itm2' => string 'two' (length=3)
Trying to access the proprerty prop3 of the content2 of the object with a string:
Standard way to get the value : $objTest->Content2->prop3
Result : 3
Test string: "Content3"
Result: 3
Test astring: "Content2->prop3"
( ! ) Notice: Undefined property: stdClass::$Content2->prop3
Hope i put everything to help understand my situation!
Thanks!
I don't know of a built-in PHP function that does this, but a function could be used to break up the string of properties and iterate through them to find the value of the last one in the string.
function get_property($object, $prop_string, $delimiter = '->') {
$prop_array = explode($delimiter, $prop_string);
foreach ($prop_array as $property) {
if (isset($object->{$property}))
$object = $object->{$property};
else
return;
}
return $object;
}
I have an object that needs to be returned, however I need to perform some pre-return manipulation before returning it.
The object has the following format:
object(PaginationHelper)[3]
public 'current_page' => int 1
public 'items_per_page' => int 10
public 'dataset' =>
array (size=10)
0 =>
object(AdvertSet)[4]
public 'Keywords' => string '' (length=0)
protected 'Adverts' =>
array (size=3) // SIZE = 3 SO REMOVE THIS FROM 'dataset' ARRAY
...
public 'LiveStatus' => boolean false
1 =>
object(AdvertSet)[5]
public 'Keywords' => string '' (length=0)
protected 'Adverts' =>
array (size=1) // SIZE = 1 SO KEEP THIS IN 'dataset' ARRAY
...
public 'LiveStatus' => boolean false
etc etc ....
[End Object]
What I need to do:
Remove all parts of the 'dataset' array that doesn't have an 'Adverts' count of 1, thereby preserving only those datasets that have an 'Adverts' array size of 1.
Retain the fact that it is an object, to be returned.
I've tried multi-dimensional recursive functions to get through this, however the fact that it's an object and not an array is making progress hard, and I'm not sure I would be able to convert from an object to an array and back again without messing up the object's internals.
Can anyone help with this? Here's what I've gotten so far with a foreach...
foreach($results as $key => $value) {
if($key == 'dataset') {
// value is right array to check count
foreach($value as $k => $v) {
echo $v;
}
}
}
It doesn't work, but that's the method I'm currently working on.
I've also tried something like:
if(count($results->dataset->(Array)AdvertSet->Adverts == 1) { }
but I can't cast AdvertSet as Array.. Any help would be greatly appreciated!
Just a quick note: it doesn't have to be removed from the array, I just eventually need the same object without those that have an Adverts count of 3. So this could involve copying to a new array without those that have an Adverts count of <> 1.
My first thought was:
foreach($PaginationHelper->dataset as &$data) {
if(count($data) !== 1)
unset($data);
}
But after reading your question for the third time, I see you want to remove only those elements with a Adverts count not equal to 1.
Looking at your structure, the Adverts array is protected, and therefore there is now way to access it without subclassing Advertset object.
So, my final answer must be: It is not possible to remove them, with this structure!
Your data structure is not really recursive and you don't need recursive traversal.
You only need to iterate over the $object->dataset array and delete items where the count of adverts is not 1. Since you're trying to filter items over a protected property, one approach would be to implement a AdvertSet::count() method that would return number of contained adverts: $object->dataset[$i]->Adverts->count() != 1. I would advise against forcing your way to access the protected property just for the filtering's sake.
I am using Code Igniter and I get following data structure after executing a query at DB
array
'application' =>
array
0 =>
object(stdClass)[19]
public 'app_id' => string '16' (length=2)
public 'app_name' => string 'dddddddd' (length=8)
public 'app_title' => string 'sdfsdf' (length=6)
public 'app_comments' => string 'sdfsdf' (length=6)
public 'active_flg' => string 'N' (length=1)
I know one way to access the values is
foreach($application as $key => $value)
$value->app_id
But I know that I will get only one record each time so I want to access the elements without using foreach.
I have tried to $application->app_id and $application['app_id'] but I keep getting error.
Can anybody please help me to understand how to access the data directly??
You are using multidimensional mixed type of array, with numeric indexing on the second level. SO, while accessing the values, you have to use them too. Like
echo $array['application'][0]->app_id;
A simple example to show you the structure of your array and how you might access it...
$objArray = array('app_id' => 7, 'app_name' => 'apps demo', 'app_title' => 'apps demo title');
$applicationArray = array('application' => array((object)$objArray));
// access the array
print $applicationArray['application'][0]->app_id;
Are you getting that result by doing the following?
$res = $this->db->query('select * from application limit 1')->result();
If so, you can put that result into an object by doing:
$app = $this->db->query('select * from application limit 1')->row();
This way you can access the properties as follows:
echo $app->app_id;
You should check out codeigniters manual on getting results.