Search code examples
phpweb-servicescodeignitersimplexml

Fixing "Warning: Illegal string offset" -- (but without losing content)


I have searched for solution for this problem but none fix my problem. The answers suggest that I use isset to check the array before working on it. But I will explain how it doesnt do it for me later.

Pre-req:
I've got a huge XML file from a tour & travel webservice which I would parse and convert to PHP array and later do some operation on it. (Filter tours mostly).

My Approach:
I'm using SimpleXML to load the xml and convert it to PHP array like so:

$xml = file_get_contents(APPPATH."tour.xml", true);
$xmlString = htmlentity_to_xml($xml); //custom method to clean XML
$Str = simplexml_load_string($xmlString, 'SimpleXMLElement', LIBXML_NOCDATA);

//converting to array
$json = json_encode($Str);
$array = json_decode($json,TRUE);

Then I'm sending this array to a fitlerTours($searchParams, $tourArray) method along with search parameters (cityName & dates) and the array itself.

Then using foreach() i'm going through each tour to look for the cityName and raising a flag if found.

The Problem
When I filter the tours (the ones which contain cityName) for dates, I'm getting this.

Severity: Warning
Message: Illegal string offset 'year'
Filename: controllers/tourFilter.php
Line Number: 78

Warning shows for offeset 'month' and 'day' also.
Here's my PHP for date filter: (Line 78 is 4th line)

if($flag == 1){
  if(!empty($fromDate)){
     foreach($tour['departureDates']['date'] AS $date){
        $dateDep = strtotime($date['year'] . "-" . (($date['month']) < 10 ? "0".$date['month'] : $date['month']) . "-" . (($date['day']) < 10 ? "0".$date['day'] : $date['day']));
        if(strtotime($fromDate) <= $dateDep && $dateDep <= strtotime($fromDate . "+".$range." days")){
          if($date['departureStatus'] != "SoldOut"){
             $dateFlag = 1;
          }
        }
     }
  }
  else{
     $dateFlag = 1;
  }
  $flag = 0;
}

if($dateFlag == 1){//Collect tours which contain the keyword & dates to $response array
   $responseArray[] = $tour;
   $dateFlag = false; //Reset Flag
}

Here's the snippet of XML:

...
<departureDates>
        <date>
            <day>7</day>
            <month>1</month>
            <year>2016</year>
            <singlesPrice>12761</singlesPrice>
            <doublesPrice>9990</doublesPrice>
            <triplesPrice>0</triplesPrice>
            <quadsPrice>0</quadsPrice>
            <shipName/>
            <departureStatus>Available</departureStatus>
        </date>
        <date>
            <day>8</day>
            <month>1</month>
            <year>2016</year>
            <singlesPrice>12761</singlesPrice>
            <doublesPrice>9990</doublesPrice>
            <triplesPrice>0</triplesPrice>
            <quadsPrice>0</quadsPrice>
            <shipName/>
            <departureStatus>SoldOut</departureStatus>
        </date>
</departureDates>
...

Now if i use the solution I found by searching around is check if the array is set properly by isset() it doesn't return true and line 78 is not executed and the data is lost. But I need the data.

This happens for only keywords i search.
Any help is appreciated.


Solution

  • The error says that the $date var is detected as string in some point...

    Characters within strings may be accessed and modified by specifying the zero-based offset of the desired character after the string using square array brackets, as in $str[42]. Think of a string as an array of characters for this purpose. See here

    So try this:

        if(is_array($date)){
            $dateDep = strtotime($date['year'] . "-" . (($date['month']) < 10 ? "0".$date['month'] : $date['month']) . "-" . (($date['day']) < 10 ? "0".$date['day'] : $date['day']));
            if(strtotime($fromDate) <= $dateDep && $dateDep <= strtotime($fromDate . "+".$range." days")){
              if($date['departureStatus'] != "SoldOut"){
                 $dateFlag = 1;
              }
            }
        }
        else {
            //If this is not an array what is it then?
            var_dump($date);
        }