PHP Illegal String Offset Warning - php

Disclaimer: I'm not a PHP programmer. I don't really consider myself a programmer at all. I was just unfortunate enough to inherit some code that doesn't work.
So I have this code. I believe it was written for PHP4, but we're using PHP5.
// Retrieve project list
$project = new CProject();
$proj = $project->getAllowedRecords( $AppUI->user_id, 'project_id, project_name');
foreach ( $proj as $k => $p ) {
$project_select_list[$k] = $p['project_name'];
}
This is supposed to populate a pick list based on the user's role, but it doesn't work. I get the "illegal string offset" warning on the line inside of the foreach loop. I think understand what it's trying to do, but I don't enough about PHP to fix it. I did a vardump on $proj and it returned this.
array(5) {
[1]=> string(4) "Roof"
[2]=> string(4) "Wall"
[3]=> string(4) "Yard"
[4]=> string(7) "Kitchen"
[5]=> string(8) "Bathroom"
}
Anyone got any hints on how to fix it? Thanks.

This seems to be produced by this:
$p['project_name'];
If $p variable is a string (as the var_dump() said), you don't have an array to access nowhere. The most probably solution is this:
foreach ( $proj as $k => $p ) {
$project_select_list[$k] = $p;
}

Related

Convert multidimensional array

How can I convert the below array to look like the one right below. I am trying to use array_map but i am confused on how to write the function.
array(3) {
["award_year"]=>
array(2) {
[0]=>
string(7) "1999-01"
[1]=>
string(7) "2010-02"
}
["award_title_user"]=>
array(2) {
[0]=>
string(1) "2"
[1]=>
string(2) "tt"
}
["award_description_user"]=>
array(2) {
[0]=>
string(1) "2"
[1]=>
string(3) "ddd"
}
}
This what i am trying to achieve:
array(2) {
[0]=>
array(3) {
["award_year"]=>
string(7) "2010-02"
["award_title_user"]=>
string(2) "tt"
["award_description_user"]=>
string(3) "ddd"
}
[1]=>
array(3) {
["award_year"]=>
string(7) "1999-01"
["award_title_user"]=>
string(1) "2"
["award_description_user"]=>
string(1) "2"
}
}
$newArr = [];
foreach($oldArr as $key=>$row) {
foreach($row as $index=>$item) {
$newArr[$index][$key] = $item;
}
}
this will solve it, but no checks if data is valid as you mentioned
First things first, #tzook-bar-noy's answer is a better answer in this case, and I am not even advocating the approach I am going to detail here.
When dealing with arrays, I always try to avoid generic loops (ie: foreach()) if I can, instead using the more functional-programming approach that you mention in your question: using functions like array_map(). However the functional-programming functions are very focused in what they do (which is their benefit: they make your code Cleaner), so to use them: you kinda gotta be wanting to do the specific operation they offer.
array_map() has a drawback for your purposes here, in that the mapped array has the same keys in the same order as the original array, which is not what you want here. You need to both turn your original array "inside out", but the ordering of the resultant array you want is the reverse of the original data. Not a good fit for array_map().
It's doable with array_map(), but it's like using a flathead screwdriver when you really need a Philips.
Here's an example:
<?php
$awards = [
"award_year" => ["1999-01", "2010-12"],
"award_title_user" => ["2", "tt"],
"award_description_user" => ["2", "ddd"]
];
$remappedAwards = array_map(function($year, $title, $description){
return [
"award_year" => $year,
"award_title_user" => $title,
"award_description_user" => $description
];
}, $awards["award_year"], $awards["award_title_user"], $awards["award_description_user"]);
$remappedAwards = array_reverse($remappedAwards);
echo "<pre>";
var_dump($remappedAwards);
echo "</pre>";
Obviously I've hardcoded the key names in here too which is less than ideal. One could contrive a generic approach, but by then we'd be so far beyond the actual intent of aaray_map() that the code complexity would be getting daft.
In other languages wherein these array-iteration functions are a bit better implemented (say JS or CFML) one might be able to come up with a half-decent answer with a .reduce() (JS, CFML) kind of operation. However PHP's array_reduce() (and its other array-iteration methods) are hamstrung by their poor implementation as they only pass the value to the callback. They really need to pass at least the index as well, and (less-often-useful, but handy sometimes ~) the array itself as additional arguments to make them anything more than a proof-of-concept. IMO, obviously (I'm biased, I do more JS & CFML than I do PHP, so my expectations are set higher).
Bottom line: array_map() was not a good fit for your requirement here, but I applaud your efforts for thinking to us it as the function-programming approach to array manipulation is definitely a better approach than generic looping where the requirement matches the functionality.

PHP object array navigation

I'm pulling data from a Blogger RSS feed. I have most of it narrowed down how I would like it to be, except for one thing. In the following object, how would I get the string in the term section? I've tried about every syntax I can think of, but I honestly have run out of ideas.
object(SimpleXMLElement)#7 (1) {
["#attributes"]=>
array(2) {
["scheme"]=>
string(31) "http://www.blogger.com/atom/ns#"
["term"]=>
string(7) "happens"
}
}
I've tried to var_dump $item->attributesand $item->#attributes with no luck.
Use the attributes() method:
$atts = $xml->attributes();
echo $atts['term'];
Alternatively, you could also use:
$xml->attributes()->{'term'};
var_dump($object->{'#attributes'}['term']);
or
$tmp = '#attributes';
var_dump($object->{$tmp}['term']);

Determine infinite nested array in PHP

SO,
I have an issue with determining recursion in arrays in PHP. Assume that I have a dynamic-generated array, which finally can looks like:
$rgData = [
['foo', 'bar', $rgTemp=[7, 31, true]],
[-5, &$rgData, 'baz']
];
(links to variables here are provided dynamically and may refer to an array itself). Another sample:
$rgData = [
['foo', 'bar', $rgTemp=[7, 31, true]],
[-5, &$rgTemp, 'baz']
];
Both arrays have some references inside, but second looks good since it's reference is not cycled. Later, due to my logic, I have to handle array via recursive functions (something like array_walk_recursive) - and, of cause, I got Fatal error due to infinite nested array recursion in case of first sample above.
My question is - how to determine if an array has infinite recursion. Note, that this question is more complicated than simple search link from inside array to itself, because we can have something like:
$rgOne = [
['foo', 'bar'],
['baz']
];
$rgTwo = [6, 'test', &$rgOne];
$rgOne[1][] = &$rgTwo;
i.e. more complicated recursion. I found that PHP can resolve this somehow in var_dump and similar functions - for example, dump of the third sample will look like:
array(2) {
[0]=>
array(2) {
[0]=>
string(3) "foo"
[1]=>
string(3) "bar"
}
[1]=>
array(2) {
[0]=>
string(3) "baz"
[1]=>
&array(3) {
[0]=>
int(6)
[1]=>
string(4) "test"
[2]=>
&array(2) {
[0]=>
array(2) {
[0]=>
string(3) "foo"
[1]=>
string(3) "bar"
}
[1]=>
*RECURSION*
}
}
}
}
i.e. *RECURSION* was caught. Currently, I've tried to resolve a matter via function:
function isLooped(&$rgData, &$rgCurrent=null)
{
foreach($rgData as $mKey=>$mValue)
{
if(is_array($mValue) && isset($rgCurrent) &&
$rgCurrent===$rgData /* that's where, it seems, I need help*/)
{
return true;
}
elseif(is_array($mValue) && isLooped($mValue, $rgData))
{
return true;
}
}
return false;
}
but with no success (and I know why - that comparison is invalid). The only idea I have now is to do weird thing, like:
function isLooped(&$rgData)
{
$rgTemp = #var_export($rgData, 1);
return preg_match('/circular references/i', error_get_last()['message']);
}
but that is sad since I need at least copy my array data to some temporary storage (and, besides, all of this looks like a glitch, not a proper solution). So, may be there are some ideas of how to do that normal way?
Update: I've found a solution via changing key in the array and then looking for it in recursive loop. This is much better than var_* functions, but still not exactly what I want. Is there a way to do this without var_* functions or changing original array?
The problem is that PHP doesn't have a mechanism to tell you whether two variables reference the same zval (internal data type representing the actual held data). This rules out keeping track of the variables you have traversed so far as a solution.
Without this feature or modifying elements (pin method) it's unfortunately not possible to detect a recursive data structure except for var_dump() or print_r() hacks.

Foreach through an array with objects and return the values and keys

array(14) {
[0]=>
object(stdClass)#2 (2) {
["set_id"]=>
int(44)
["name"]=>
string(7) "Cameras"
}
[1]=>
object(stdClass)#3 (2) {
["set_id"]=>
int(38)
["name"]=>
string(11) "Cell Phones"
}
[2]=>
object(stdClass)#4 (2) {
["set_id"]=>
int(39)
["name"]=>
string(8) "Computer"
}
The Above is my Data.
I want to return the object names ["Set_ID"] etc and the value.
I have googled and googled and tried examples from here with various failures and now I'm giving up.
I have tried to simply manually return data - ie
foreach($result as $results2)
{
foreach($results2->name as $item)
{
echo "<pre>";
print_r($item);
echo "</pre>";
}
}
I have tried all sorts of flavors of it I had kind of hoped the above would at least return data and it didn't - just errored.
In the end, I'd like to be able to both pull names and data. I don't want to have to manually find element names and code it as $result->SET_ID or whatever - I want to be able to just feed SET_ID in as a variable. I think my problem lies with it being an array of objects and I cant access that object name and all..
Im a noob, so any kind of like detailed explanation wouldn't hurt my feelings so I can learn something.
Instead of foreach($results2->name as $item) use foreach($results2 as $item). $results2->name is not an array thus causing the error.
You can read about object iteration in PHP here
foreach($result as $results2)
{
echo $results2->name.' '.$results2->set_id;
}

"Transfer" object properties to object of different class

I have one object being the result of a database query, looking something like this (var_dump output):
object(stdClass)#17 (6) {
["id"]=>
string(1) "1"
["title"]=>
string(20) "Some Title"
["description"]=>
string(41) "Some really good stuff. Description here."
["slug"]=>
string(19) "some-slug-url"
["picture_url"]=>
NULL
["price"]=>
string(4) "5.99"
}
I just need all property values "transferred" to a different class which has the same property names. Is there a simple way to do this?
Take a look at PHP's get_object_vars()-function to achieve the desired effect without tons of assignment statements:
foreach (get_object_vars($sourceObject) as $name => $value) {
$destinationObject->$name = $value;
}
You should make sure that you add sufficient error-checking to this, depending on your needs.
The simple and "failsafe" solution
$target = new MyClass;
$target->id = $source->id;
$target->title = $source->title;
// and so on
Its a little bit more to code, but the benefits are
If some property of $source change, you will notice it (because its missing in $target)
You can name the properties of $target completely independent from $source
You see, what happens

Categories