0

Using str_replace() to replace values in a couple paragraphs of text data, it seems to do so but in an odd order. The values to be replaced are in a hard-coded array while the replacements are in an array from a query provided by a custom function called DBConnect().

I used print_r() on both to verify that they are correct and they are: both have the same number of entries and are in the same order but the on-screen results are mismatched. I expected this to be straightforward and didn't think it needed any looping for this simple task as str_replace() itself usually handles that but did I miss something?

$replace = array('[MyLocation]','[CustLocation]','[MilesInc]','[ExtraDoc]');
$replacements = DBConnect($sqlPrices,"select",$siteDB);
$PageText = str_replace($replace,$replacements,$PageText);

and $replacements is:

Array
(
    [0] => 25
    [MyLocation] => 25
    [1] => 45
    [CustLocation] => 45
    [2] => 10
    [MilesInc] => 10
    [3] => 10
    [ExtraDoc] => 10
)
DonP
  • 725
  • 1
  • 8
  • 27
  • Can you show us an example of the `$replacements` array please – RiggsFolly Jan 13 '19 at 23:54
  • You cannot use str_replace on array. str_replace use on string. – Abed Putra Jan 13 '19 at 23:56
  • @AbedPutra From: http://php.net/manual/en/function.str-replace.php "Search: The value being searched for, otherwise known as the needle. An array may be used to designate multiple needles.". Further to this all parameters may be an array. –  Jan 14 '19 at 00:01
  • @MattFryer oh sorry, I am not read carefully. for DonP have you try this https://stackoverflow.com/questions/24554723/str-replace-for-multiple-value-replacement – Abed Putra Jan 14 '19 at 00:16
  • @AbedPutra No need to apologise : ) –  Jan 14 '19 at 00:17
  • I added the $replacements array any and with it formmated, I see the problem but not sure what to do about it so advice is appreciated. On the other hand, since the names within **[** and **]** are the same as the column names in the database, maybe there is another more direct way to do the replacements. – DonP Jan 14 '19 at 00:20
  • @Matt Fryer [MyLocation] is one of the strings to be replaced by the column that is also called MyLocation. The strings within the text to be replaced are surrounded by square brackets but otherwise match the column names of the database table. The syntax is straightforward but the problem is to do with the array of values from the query and I need to get rid of the numeric ones. Otherwise there are twice as many results in that array as in the other so no wonder they are mismatched. – DonP Jan 14 '19 at 00:33

2 Answers2

0

Once I saw what the $replacements array actually looked like, I was able to fix it by filtering out the numeric keys.

$replace = array('[MyLocation]','[CustLocation]','[MilesInc]','[ExtraDoc]');
$replacements = DBConnect($sqlPrices,"select",$siteDB);

foreach ($replacements as $key=>$value) :
    if (!is_numeric($key)) $newArray[$key] = $value;
endforeach;

$PageText = str_replace($replace,$newArray,$PageText);

The former $replacements array, filtered to $newArray, looks like this:

Array
(
    [MyLocation] => 25
    [CustLocation] => 45
    [MilesInc] => 10
    [ExtraDoc] => 10
)
DonP
  • 725
  • 1
  • 8
  • 27
  • You could also have perhaps changed your db query fetch mode from both to associative. – Progrock Jan 14 '19 at 04:09
  • or `$filtered = array_filter($data, 'is_string', ARRAY_FILTER_USE_KEY)`. – Progrock Jan 14 '19 at 04:15
  • Thank you, I got it working and posted my code already as an answer. As for changing the db query fetch mode, I suppose it would be possible but the custom function containing it is used on five of my sites so perhaps not something I want to mess with at this time. – DonP Jan 14 '19 at 09:17
0

-- edited: Removed some non sense statements --

@DonP, what you are trying to do is possible.

In my opinion, the strtr() function could be more beneficial to you. All you need to make a few adjustments in your code like this ...

<?php
$replacements = DBConnect($sqlPrices,"select",$siteDB);
$PageText = strtr($PageText, [
  '[MyLocation]' => $replacements['MyLocation'],
  '[CustLocation]' => $replacements['CustLocation'],
  '[MilesInc]' => $replacements['MilesInc'],
  '[ExtraDoc]' => $replacements['ExtraDoc'],
]);
?>

This code is kinda verbose and requires writing repetitive strings. Once you understand the way it works, you can use some loops or array functions to refactor it. For example, you could use the following more compact version ...

<?php
// Reference fields.
$fields = ['MyLocation', 'CustLocation', 'MilesInc', 'ExtraDoc'];

// Creating the replacement pairs.
$replacementPairs = [];
foreach($fields as $field){
  $replacementPairs["[{$field}]"] = $replacements[$field];
}

// Perform the replacements.
$PageText = strtr($PageText, $replacementPairs);
?>
asiby
  • 3,229
  • 29
  • 32
  • Thank you but not sure what you meant that the placeholders were not the same as the table columns unless it was in reference to your own code. They were not intended to be the same and no need for them to be and for my code they could be anything as long as they are in the $replace array and match in the array position what is to replace them. It's basically just one string being replaced with another value. See below for my own solution which I had already posted but again thanks for the additional ideas which look interesting. – DonP Jan 14 '19 at 09:28
  • @DonP, I need to edit that out because it does not make sense. It was late and that was a brain fart. Other than that, I see two solution. 1. You can request you MySQL connection to return an array with only associative key, or use `strtr()` to explicitly specify which strings you need to translate to what value. – asiby Jan 14 '19 at 14:10
  • The answer at https://stackoverflow.com/questions/9556794/double-results-in-my-array-mysql-fetch-array will show you how to request either numeric keys only or associative keys in a query result. By default, both are returned. Depending on what DB library you are using, you may need to find out how to pass the appropriate options. – asiby Jan 14 '19 at 14:20
  • I’ll check it out and for referencd using mysqli. Never occurred to me that there might be such an option so thank you for the idea. – DonP Jan 15 '19 at 00:38
  • Thanks mate. It's a feature that I hate in some MySQL clients. It makes applications resource hungry and causes poor performances due to the way they return double the amount of result that is need. – asiby Jan 15 '19 at 16:34
  • Unfortunately, while assoc fixed this immediate issue where even the code in my original question worked, it broke countless other things throughout the five sites that share the code so I had to go back to the way it was and use the fix in my answer instead. – DonP Jan 16 '19 at 18:46
  • In that case, you can keep it the way it was (with assoc and numeric keys) and use array_filter to extract only the part of the array that has the non numerical keys. Then you can use the result of that function for the replacements. That way, you won't break any legacy code. – asiby Jan 16 '19 at 19:50