1

I use a config.php file that returns an array. Before releasing the project, I usually manually change the 'apiKey' value that I use while developing in the file. I forget to perform this replacement sometimes, so I'm looking for a programmatical way to find this in a string version of the file:

'apiKey' => '1234567890'

and replace with this:

'apiKey' => 'YourAPIKeyHere'

The development apiKey value, spaces, tabs and formatting are inconsistent (Developer/IDE specific), so I guess there are wildcards for that?

Then I can just make the change in my deployment script.

Edit to show sample of config.php (which will be read into a string, edited, then re-written as a file).

<?php
return array(
// Comments with instruction exist throughout the file. They must remain.
'apiKey' => 'ecuhi3647325fdv23tjVncweuYtYTv532r3',
...
);

Edit: **There are instructional comments in the config.php file that must remain. So re-writing a modified array will lose the comments, and that is undesirable.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
user1730452
  • 155
  • 1
  • 8

5 Answers5

1

I assume that you have a config file such as;

return [
 'dbname' = 'project',
 'username' = 'root',
 'password' = '123456',
  .
  .
  .
 'apiKey' => '1234567890',
]

So you can make a small helper method then you can use it before relasing your project..

function reset_config()
    {
        $file_path = "your/config/path";
        $configs = require_once($file_path);

        array_walk_recursive($configs, function (&$config, $key) {
            $config = "your " . $key;
        });

        $string = var_export($configs,true);

        $new_config_file = <<<HEAD
    <?php
    return $string;
HEAD;

        file_put_contents($file_path, $new_config_file);
    }

so all you need to use reset_config() function before relasing the project

Teoman Tıngır
  • 2,766
  • 2
  • 21
  • 41
  • I need to say that, after using above function, new config file might be look like messy. So if you're using phpstorm, you can use the `CTRL + ALT + L` for reformat your codes (mean array) – Teoman Tıngır Aug 26 '18 at 13:02
  • Tingir I appreciate the answer but I can't get it to work. the "your ".$key; seems to be where I fail. – user1730452 Aug 26 '18 at 16:10
  • There are comments in the file that must remain. That's why I needed to use a find and replace method. – user1730452 Aug 26 '18 at 16:18
  • @user1730452 I'm trying in localhost right now, and it seems work as well without comments :/ But as you mentioned you need to make regex pattern if you want to keep comments – Teoman Tıngır Aug 27 '18 at 07:08
1

Save the config file's text in a variable called $content.

Then call:

 $content = preg_replace("~'apiKey'\s*=>\s*'\K[^']+~", 'YourAPIKeyHere', $content, 1);

Then overwrite the file with the updated variable.

http://php.net/manual/en/function.preg-replace.php

\s* means match zero or more whitespace characters.

\K means restart the match from this point.

[^']+ means match one or more non-single-quote character.

Regex101 Demo

PHP Demo

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
  • @mickmacusa Nice! RegEx makes an elegant solution as opposed to looping through a file as array like I ended up doing. I could never wrap my head around regex to feel comfortable. I'm implementing this into the project and accepting this answer as it was what I originally requested, a regex. My question was edited and someone actually replaced the regex part with something they figured I really wanted. Go figure. lol. One question. I tried with YourAPIKeyHere! and it failed. Do I need to escape the replacement value? – user1730452 Aug 28 '18 at 00:01
  • No, the replacements string doesn't need any special markup -- just a raw text string. If you show me your new snippet, I'll have a look. You are welcome to overwrite my edit if it does not accurately depict your issue or you wish to add more relevant details. – mickmackusa Aug 28 '18 at 00:02
  • $config = file_get_contents('app/config.php');$config = preg_replace("~'apiKey'\s*=>\s*'\K[^']+~", 'YourAppAPIKeyHere!', $config, 1); $zip1->addFromString('app/config.php', $config); Fails with !. Although I would probably never use special characters. – user1730452 Aug 28 '18 at 00:03
  • May I see a pastebin of your text file? or does it contain sensitive data? I don't see anything out of place in your code. As a blind guess, perhaps add `i` after the closing pattern delimiter (the second `~`) to make the pattern case-insensitive. Maybe your `apiKey` has slightly varied casing. ...My pattern will not find/match `apikey` because it is case-sensitive. – mickmackusa Aug 28 '18 at 00:05
  • It worked fine without the exclamation mark. When it failed it eliminated the entire line. I can share the file but don't know how to do a pastebin. – user1730452 Aug 28 '18 at 00:12
0

You can use this simple RegEx to match any line containing a key between the apostrophes:

'apiKey' => '[^']+'

The [^']+ will find one or more characters between single quotes. Just replace with your new line. Edit: Your replacement string would simply be:

'apiKey' => 'EnterYourAPIKeyHere' 
Poul Bak
  • 10,450
  • 5
  • 32
  • 57
  • But I don't know what the actual key value is. All I know is that there is: 'apiKey'=>'?', - and a line break. – user1730452 Aug 26 '18 at 15:48
  • Yes, the new key is always 'EnterYourAPIKeyHere' – user1730452 Aug 26 '18 at 15:50
  • I guess I just can't wrap my head around how to use RegEx. Could you provide more detail? – user1730452 Aug 26 '18 at 15:58
  • Well, you asked about RegEx, so I answered showing using RegEx. RegEx is really too complicated for a comment here. – Poul Bak Aug 26 '18 at 16:03
  • The issue is complicated. That's why I needed help. It MUST be done with some type of RegEx but there's one of my weaknesses. LOL. I thought it would only be a line or two of code. You have pointed me in the right direction. – user1730452 Aug 26 '18 at 16:23
0

As i suggested you can use the PHP tokenizer extension functions to achieve your purpose

function replaceApiKey($configpath,$newKey='test',$newpath=''){
    if(file_exists($configpath)&&is_readable($configpath)&&is_file($configpath))
        $string = file_get_contents($configpath);
    else 
        return false;

    $tokens=token_get_all($string);
    $start=false;

    foreach($tokens as $key=>$token){
        if(is_array($token)&&stripos($token[1],'apiKey')){
            $start=true;
            $tokens[$key]=$token[1]; 
            continue;
        }
        if($start&&$token&&is_array($token)&&token_name($token[0])!=="T_COMMENT"&&token_name($token[0])!=="T_DOUBLE_ARROW"&&!ctype_space($token[1])){
            $token[1]=$token[1][0].$newKey.$token[1][strlen($token[1])-1];
            $start=false;
        }
        if(is_array($token)) $tokens[$key]=$token[1]; 
    }
    if(empty($newpath)) 
        $newpath=$configpath;
    if (file_put_contents($newpath, join('',$tokens)))

        return true;
    else
        return false;}

This function take in parameter the config path,tokenize the content then search and replace the old apiKey by the new one and save the changes in the new path...

Elementary
  • 1,443
  • 1
  • 7
  • 17
  • This would loose the comments that must remain in the file. See original post. – user1730452 Aug 26 '18 at 19:39
  • the comment is kept in my test.You just don't test it right? – Elementary Aug 26 '18 at 19:40
  • I'm sorry. I tested a lot of suggestions from here and from my colleagues. I was wrong. Yours did keep the comments but replaced the original file. However, with little modification I can see where it could just return the string leaving the original file intact (as desired). – user1730452 Aug 26 '18 at 19:58
  • if the code replace the original file it is because you didn't fill the newpath argument...Did you really test my code...? – Elementary Aug 26 '18 at 20:01
  • I see... I did test your code. Right after you posted it and it failed with php error. It was copied and tested again right as we came up with the solution. Thats when we saw it replaced the original file. And since there was a solution, I just didn't move any further with it. – user1730452 Aug 26 '18 at 20:16
  • i'm happy you finally find your solution...Now as you see you can achieve it many different ways.However your solution may not work as expected if you have something like `'apiKey' =>/*some comment here*/ 'EnterYourAPIKeyHere'` and for the little i know you really love those comments and don't want to loose them.So think about it to choose the most efficient code. – Elementary Aug 26 '18 at 20:23
0

I solved the issue by reading the file into an array and replacing the line with 'apiKey':

$array = file('app/config.php');
$string = "";
for($i = 0, $maxi = count($array); $i < $maxi; $i++)
{
    if(strpos($array[$i],'apiKey')>0){
        $string.="  'apiKey' => 'YourAppAPIKeyHere',\r\n\r\n";
    }else{
        $string.=$array[$i];
    }
}

It may not be the most elegant solution but it works. Until someone doesn't format their code right. For this reason, I would still like to use a RegEx that isolates the replacement to the required pattern. But RegEx is something I just don't get into, and there's other issues to resolve now.

Inspired by everyone who helped.

Feedback appreciated.

user1730452
  • 155
  • 1
  • 8