I have the following function which returns a SimpleXML object into a normal array. It seems to work fine, however if I turn error reporting on then I get lots of warnings say:
Warning: get_class() expects parameter 1 to be object, string given
But it still seems to be working somehow. Any ideas how I can get it to work without the errors?
function convert($content){
$data = (array)$content;
foreach ($data as $k => $v){
if(strpos(get_class($v),"SimpleXML")!==false){
$data[$k] = XMLArray($v);
}
}
return $data;
}
simply add is_object check. You are getting a warning because it is running in a loop. for some value of $v it is an object and that part is running fine but for some value $v is not an object. You are getting warning in those cases when $v is not an object.
function convert($content){
$data = (array)$content;
foreach ($data as $k => $v){
if(is_object($v) && strpos(get_class($v),"SimpleXML")!==false){
$data[$k] = XMLArray($v);
}
}
return $data;
}
I think it because of you are passing $v instead of $k
function convert($content){
$data = (array)$content;
foreach ($data as $k ){
if(strpos(get_class($k),"SimpleXML")!==false){
$data[$k] = XMLArray($k);
}
}
return $data;
}
check this
Related
i have string of html which i want to explode by <br>, but sometimes it can be inside of other tags.
if (in_array($param, $customOrdering, true) && $value) {
$ordering = array_search($param, $customOrdering, true);
$segments[$ordering] = [];
if (in_array($param, $explodeParams, true)) {
$values = explode('<br>', $value);
foreach ($values as $v) {
$testing_value = $v;
if (!empty(trim(strip_tags($testing_value)))) {
array_push($segments[$ordering], $this->createSegmentFromParam($param, $v));
138 } elseif (!empty(trim($v)) && $segments[$ordering]) {
139 end($segments[$ordering])->value_raw .= strip_tags($v, $this->allowedTags);
}
}
} else {
array_push($segments[$ordering], $this->createSegmentFromParam($param, $value));
}
}
declaration of createSegmentFormParam
#return ArrayHash
private function createSegmentFromParam($param, $value)
and i have this output from phpStan
138 Right side of && is always false.
139 Cannot access property $value_raw on false.
any ideas how to pass on ? code working well
There is still an open issue for similar behaviour or PHP Stan - False negative with array_push on property
Try not using array_push and replace it on line 138 with the following:
$segments[$ordering][] = $this->createSegmentFromParam($param, $v);
Apart from this in the beginning of your code array_search may return FALSE you do want to check this before going further down the code...
I need to get index of from array of objects without using loop as per the key name using PHP. Here I am explaining my code below.
$arr = array(array("name"=>"Jack","ID"=>10),array("name"=>"Jam","ID"=>11),array("name"=>"Joy","ID"=>12));
$key = array_search('Jack', $arr);
echo $key;exit;
Here my code does not give any output. By using some key name I need the index of that object present inside array and also I dont want to use any loop. I need Is ther any PHP in build method so that I can get the result directly.
$arr = array(array("name"=>"Jack","ID"=>10),array("name"=>"Jam","ID"=>11),array("name"=>"Joy","ID"=>12));
function myfunction($v){return $v['name'];}
echo array_search('Jack', array_map( 'myfunction', $arr ));
<?php
$arr = array(array("name"=>"Jack","ID"=>10),array("name"=>"Jam","ID"=>11),array("name"=>"Joy","ID"=>12));
//calling function searchByName
$key = searchByName('Jasck',$arr);
if($key != '-1'){
print_r($arr[$key]);
}else{
echo "No match found";
}
//function to chek if the name is there or not.
function searchByName($name, $array) {
foreach ($array as $key => $val) {
if ($val['name'] == $name) {
return $key;
}
}
return '-1';
}
sandbox
I am running this against an associative (non-numerical keys) array that is 80K lines, decoded from a 2.1K json file:
$ret = array();
function recursive(array $array, $tableName, $level=''){
global $ret;
$tableData = array();
foreach($array as $key => $value){
if(!is_array($key)) $k = $key; // keep array keys for tablename
if(is_array($value)){
$key = is_int($key) ? $tableName : $key; //skip empty subarrays
recursive($value, $level=$key);
} else{
$tableData=[$tableName, $k, $value];
}
if (!empty($tableData))
{array_push($ret, $tableData);
}
}
return $ret;
}
$ret =(recursive($array, 'project'));
The json data contains empty sub-arrays which are discarded during the 'is_int($key) recursive loop. This is a typical file size that will be processed and the function is taking over 2 mins to run - which may be as good as it gets - but I wanted to ask if there were any ways to speed this function up by better coding.
thank you,
It seems to be always true: if(!is_array($key)) $k = $key;
You are don't use the $level variable. Why do you need it?
Globals are really bad idea. You probably need to send variables to your function by link instead of value:
function recursive(&$data, &$result, $tableName)
{
//some of your logic here
//...
//if you need a recursion call
recursive($data, $result, $tableName);
}
//function call
$result = [];
recoursive($data, $result, 'project');
//all of your data now in the result variable
Also it may be a good idea to read and process your data by chunks. Iterators or generators can help you with this.
I'm working with a JSON string. I'm converting it to an associative array to find specific values and change those values when a certain key is found (['content']). The depth of the array is always unknown and will always vary.
Here is the function I wrote. It takes an array as an argument and passes it by reference so that the variable itself is modified rather than a copy of it scoped locally to that function.
$json_array = json_decode($json_string, true);
function replace_data(&$json_array, $data='REPLACE TEST')
{
foreach($json_array as $key => $value) {
if ($key == 'content' && !is_array($value)) {
$json_array[$key] = $data;
} else {
if (is_array($value)) {
replace_data($value, $data);
}
}
}
}
replace_data($json_array, "test test test");
var_dump($json_array);
What I'm expecting to happen is every time a key ['content'] is found at no matter what depth, it replaces with that value specified in the $data argument.
But, when I var_dump($json_array) Those values are unchanged.
What am I missing?
With array_walk_recursive:
function replace_data($json_array, $data = 'REPLACE TEST') {
array_walk_recursive($json_array, function (&$value, $key) use ($data) {
if (!is_array($value) && $key === 'content') {
// $value passed by reference
$value = $data;
}
});
return $json_array;
}
And without references:
function replace_data($json_array, $data = 'REPLACE TEST') {
foreach ($json_array as $key => $value) {
if (is_array($value)) {
$json_array[$key] = replace_data($value, $data);
} elseif ($key === 'content') {
$json_array[$key] = $data;
}
}
return $json_array;
}
To expand on my comment, you need another reference here:
foreach($json_array as $key => &$value) {
That way, a reference to the original value is passed when you make the recursive call, rather than the local copy created with the foreach loop.
From the PHP manual entry for foreach:
In order to be able to directly modify array elements within the loop precede $value with &. In that case the value will be assigned by reference.
You'll also see in the manual that it recommends unsetting the reference to $value after the loop. Even though it probably won't cause any problems if you don't do that in your function, it's best to be in the habit of always unsetting references created in foreach loops like that. It can cause some strange looking problems if you don't.
From PHP7.4, "arrow function" syntax offers a clean and short approach.
As leafnodes are iterated, if the key is content, then replace the text, otherwise do not change the value.
There are no returns being used. All mutations are applied directly to the passed in variables prefixed with &.
function replace_data(&$array, $replaceWith = 'REPLACE TEST')
{
array_walk_recursive(
$array,
fn(&$v, $k) => $v = ($k === 'content' ? $replaceWith : $v)
);
}
replace_data($json_array, "test test test");
var_export($json_array);
I am trying to generate an MS Excel spread sheet using PHPExcel 1.7.6 . I am having trouble determining the structure of the array expected.
The code that builds up the columns and rows is as follows:
function _headers() {
$i=0;
foreach ($this->data[0] as $field => $value) {
if (!in_array($field,$this->blacklist)) {
$columnName = Inflector::humanize($field);
$this->sheet->setCellValueByColumnAndRow($i++, 4, $columnName);
}
}
$this->sheet->getStyle('A4')->getFont()->setBold(true);
$this->sheet->getStyle('A4')->getFill()->setFillType(PHPExcel_Style_Fill::FILL_SOLID);
$this->sheet->getStyle('A4')->getFill()->getStartColor()->setRGB('969696');
$this->sheet->duplicateStyle( $this->sheet->getStyle('A4'), 'B4:'.$this->sheet->getHighestColumn().'4');
for ($j=1; $j<$i; $j++) {
$this->sheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($j))->setAutoSize(true);
}
}
function _rows() {
$i=5;
foreach ($this->data as $row) {
$j=0;
foreach ($row as $field => $value) {
if(!in_array($field,$this->blacklist)) {
$this->sheet->setCellValueByColumnAndRow($j++,$i, $value);
}
}
$i++;
}
}
I'm currently getting an 'Invalid argument supplied for foreach()' error.
I would appreciate it if somebody can outline the correct array structure required.
As IsisCode said, it sounds like you're looking in the wrong direction by associating the problem with PHPExcel. That error is generally just saying that the first argument supplied to foreach() isn't an array.
I don't see anything indicating that the problem is explicitly with the initial foreach in the _headers() method though. If there's a non array element in $this->data then your _rows() method could produce the error as well.
Given:
$this->data = Array(
Array('foo' => 'bar'),
'baz'
)
That would cause the second foreach in _rows() to fail, as an example. Your error message should be able to point you to which foreach() is failing, but ultimately it sounds like you've got a non-array element in $this->data where you don't expect it. If that can't be helped, then consider verifying you're dealing with an array before calling foreach:
function _rows() {
$i=5;
foreach ($this->data as $row) {
$j=0;
if(!is_array($row)) { continue; } // Ignore non-array elements
foreach ($row as $field => $value) {
if(!in_array($field,$this->blacklist)) {
$this->sheet->setCellValueByColumnAndRow($j++,$i, $value);
}
}
$i++;
}
Verifying the type of a variable before handing it to a type-specific function is never a bad idea and can save a lot of headache in general.