1

I have a dynamic PHP generated array ($mapHitArriving) based on arriving guests which results like the following:

[0] => Array
    (
        [id] => 1098
        [source] => 31
        [name] => Steve test1
        [date] => 2020-12-19
        [dateLast] => 2020-12-20
        [cost] => 250
        [unitno] => 1
        [utitle] => Queen Plus Room
    )

[1] => Array
    (
        [id] => 1099
        [source] => 31
        [name] => Steve Test2
        [date] => 2020-12-19
        [dateLast] => 2020-12-20
        [cost] => 250
        [unitno] => 3
        [utitle] => Queen Plus Room
    )
    

I'm trying to assign variables IF [unitno] is present. The variable is based on the unit number and has a value of the unit number and a concantonated 'a' since we're targeting arriving guests. Research has me looking at using array_search and targeting the index column of "unitno".

Using the following only produces 1 result. Only the variable for unit3 is created.

if(array_search(1,array_column($mapHitArriving, 'unitno'))== TRUE) { $unit1 = '1a'; };
if(array_search(2,array_column($mapHitArriving, 'unitno'))== TRUE) { $unit2 = '2a'; };
if(array_search(3,array_column($mapHitArriving, 'unitno'))== TRUE) { $unit3 = '3a'; };
if(array_search(4,array_column($mapHitArriving, 'unitno'))== TRUE) { $unit4 = '4a'; };
if(array_search(5,array_column($mapHitArriving, 'unitno'))== TRUE) { $unit5 = '5a'; };
if(array_search(6,array_column($mapHitArriving, 'unitno'))== TRUE) { $unit6 = '6a'; };
if(array_search(7,array_column($mapHitArriving, 'unitno'))== TRUE) { $unit7 = '7a'; };

Why does only the second instance of [unitno] create it's result? Being that they are independent array_search conditions I'm expecting a result for both unit1 and unit3.

Should I be searching and assigning differently as a best practice?

EDIT: adding a reference to Identical vs Equal operators related to the problem encountered.

EDIT 2: The original logic seems to fail when introducing the comparison to other arrays. Initially we look to see if guests are arriving (Array: $mapHitArriving - result: unit id concantonated with 'a'). Then we look to see who's Departing (Array: $mapHitDeparting - result: '1d') and lastly who is neither Arriving or Departing which is Staying (Array: $mapHitStaying - result: no concantonated letter just the unit id). It seems the first conditional is evaluating as TRUE so the others fail to execute. This condition was not present when there was some result of the initial array so I believe I need declare the array even if empty(?):

if(array_search(1,array_column($mapHitArriving, 'unitno'))!== FALSE) { $unit1 = '1a'; }
elseif (array_search(1,array_column($mapHitDeparting,'unitno'))!== FALSE) { $unit1 = '1d'; }
elseif (array_search(1,array_column($mapHitStaying,'unitno'))!== FALSE) { $unit1 = '1'; }
Burndog
  • 711
  • 2
  • 8
  • 21

2 Answers2

2

Read the manual, especially https://www.php.net/manual/en/function.array-search.php#refsect1-function.array-search-returnvalues

See the:

Warning This function may return Boolean false, but may also return a non-Boolean value which evaluates to false

What does array_search(1,array_column($mapHitArriving, 'unitno')) returns? It returns 0. Which is definitely not true.

Fix your check to:

if(array_search(1,array_column($mapHitArriving, 'unitno')) !== false) { $unit1 = '1a'; };
if(array_search(2,array_column($mapHitArriving, 'unitno')) !== false) { $unit2 = '2a'; };
// etc 

As a sidenote I would advice to store similar data as array, and not as variables. You can do something like this:

$unitnoKeys = array_map(
    function($v) { return $v . 'a'; }, 
    array_column($mapHitArriving, 'unitno')
);
$unitnos = array_fill_keys($unitnoKeys, true);
print_r($unitnos);
// outputs
Array
(
    [1a] => 1
    [3a] => 1
)
// after that you can chek whether you have a certain key 
if (isset($unitnos['1a'])) {
    // do stuff
}
if (isset($unitnos['5a'])) {
    // do other stuff
}
u_mulder
  • 54,101
  • 5
  • 48
  • 64
  • !== false as opposed to == true, in other words is not False as opposed to is True. Crazy as it seems it's the same, but works perfectly. Thank you. – Burndog Dec 19 '20 at 17:48
  • Nope, `!==` is opposed to `===`. Read about the diffetrence between `==` and `===`. Topic is here https://stackoverflow.com/questions/2063480/the-3-different-equals – u_mulder Dec 19 '20 at 17:52
1

@u_mulder has pretty much already answered this question. However, there are a few additional points to cover...

Original Problem

As @u_mulder has already said: your code is working correctly; the problem is that for the first instance your array_search(array_column()) condition returns 0 which is equivalent to FALSE when using ==.

Here's the first point where I'm going to differ from @u_nudler.

The reason it returns 0 is because array_column numerically re-indexes the returned result. In your case it would return:

array(
    0 => 1,
    1 => 3
);

Which means your array_search matches 0 => 1 in your fist if statement and then evaluates the expression:

(0 == TRUE) => FALSE

N.B.

This has nothing to do with the original keys or the array_search function.

Basic Fix

There are a couple ways to fix this:

  1. Use !== FALSE instead of == TRUE

    if( array_search(array_colum()) !== FALSE )
    
  2. Use is_int() instead of == TRUE

    if( is_int(array_search(array_column())) )
    
  3. Index array_column on your id field instead

    array_column($mapHitArriving, 'unitno', 'id')
    

Additional point

Assigning your values to variables in this way means that some of the variables won't be assigned. So when you come to use them you need to carry out additional checks to make sure that the variable has been initiated. If you don't then PHP will raise Notices: not a major problem, but best avoided.

Changing the code

Whilst the above will fix the problem in the short term. Structuring your code in this way isn't good practice.

You would do far better to simply store the relevant data in an array. Which you can simply generate with array_column which you're using anyway!

$units_arriving = array_column($mapHitArriving, 'unitno');

Storing the values in an array also means that you can easily use a loop to work through the values, like:

foreach($units_arriving as $unit){
    echo "Unit {$unit} is arriving today!\n";
}

This reduces your code massively Without a loop your code would likely look like:

echo "Unit {$unit1} is arriving today!\n";
echo "Unit {$unit2} is arriving today!\n";
echo "Unit {$unit3} is arriving today!\n";
echo "Unit {$unit4} is arriving today!\n";
echo "Unit {$unit5} is arriving today!\n";
echo "Unit {$unit6} is arriving today!\n";
echo "Unit {$unit7} is arriving today!\n";
Steven
  • 6,053
  • 2
  • 16
  • 28