2

I am working on a program in which an addon needs to modify a system file.

I have a small method in which I am finding the beginning of the string in the file like this:

     /**
     * @param $fileName
     * @param $str
     *
     * @return int
     */
    private function getLineWithString($fileName, $str)
    {
        $lines = file($fileName);
        foreach ($lines as $lineNumber => $line) {
            if (strpos($line, $str) !== false) {
                return $line;
            }
        }
        return -1;
    }

I am calling that from within the method where I need to pull that string out to replace it like this:

//  Set our file to use
$originalFile = 'file.php';

// Find The array['key'] string
$myString = "\$array['key']";

// Process - Find it
$lineNo = $this->getLineWithString($originalFile, $myString);

Then echo $lineNo; returns $array['key'] = array(.

However, I need it to return the entire multi-line array/string up until the next ; (semicolon).

How would I go about this?

Thanks

* EDIT *

My PHP file contents are like this:

<?php 
    /**
     * Comment here 
    */
     $first_array = array( 
         'key1' => 'val1', 
         'key2' => 'val2', 
         'key3' => 'val3', 
         'key4' => 'val4', 
         'key5' => 'val5' 
    );

    $second_array = array( 
        'key1' => 'val1', 
        'key2' => 'val2' 
    ); 
    ...

I have tried the suggestion from @Scuzzy

This is in my method now:

// Open Existing File And Get Contents
$myFile = file_get_contents('myFile.php');

$tokens = token_get_all($myFile);

foreach ( $tokens as $token ) {
    if (is_array($token)) {
        if( $token[0] === T_CONSTANT_ENCAPSED_STRING and strpos( $token[1], "\n" ) !== false )
        {
            var_dump( $token );
        }
    }
}

However, this doesn't return anything.

I need to return something like:

$second_array = array( 
    'key1' => 'val1', 
    'key2' => 'val2' 
);

As a string I can manipulate and rewrite.

3
  • 1
    Perhaps sample input and desired output would make this easier. Commented Mar 30, 2017 at 23:11
  • pastebin.com/CA0Du9Ly I came up with a way to find the array() blocks, but not a nice way to get the var prefixing it. You could tweak it to instead capture the starting and ending line numbers. Commented Mar 31, 2017 at 0:08
  • I'm doing something similar now using is_array($token)... ;) Commented Mar 31, 2017 at 0:11

2 Answers 2

2

Rather than trying to parse a PHP file in PHP, depending on what you're needing to do, you might be able to use var_export().

require_once($filename);

// variables are now in global scope
// manipulate as necessary
$first_array['this_key'] = 'that value';

$str = '$first_array = '.var_export($first_array, TRUE).";\n\n";
$str .= '$second_array = '.var_export($second_array, TRUE).';';

// output the updated arrays back to the file
file_put_contents($filename, $str);
Sign up to request clarification or add additional context in comments.

3 Comments

I like this, but I need to comment out the one I find or remove it completely as I am building new functionality. I was really hoping for a way to find various segments and comment or remove then I was going to append my new code to the file as needed.
^^^ Playing with this now, I think I can make this work. Thanks @Derek.
Yep, to remove it completely, you can simply unset() that key in the array in question prior to the var_export().
2

I would be looking into http://php.net/manual/en/function.token-get-all.php and in particularly T_CONSTANT_ENCAPSED_STRING that have new line characters in them

token.php

$code = file_get_contents('token.code.php');

$tokens = token_get_all( $code );

foreach ( $tokens as $token ) {
  if (is_array($token)) {
    if( $token[0] === T_CONSTANT_ENCAPSED_STRING and strpos( $token[1], "\n" ) !== false )
    {
      var_dump( $token );
    }
  }
}

token.code.php

<?php    
$bar = "single line";
$foo = "hello
multi
line
world";
$bar = 'single line';
$foo = 'hello
multi
line
world';

will print the multi line but not the single lines:

array(3) {
  [0]=>
  int(318)
  [1]=>
  string(27) ""hello
multi
line
world""
  [2]=>
  int(4)
}
array(3) {
  [0]=>
  int(318)
  [1]=>
  string(27) "'hello
multi
line
world'"
  [2]=>
  int(9)
}

9 Comments

Tried this, but it didn't output anything from my php file
appologies, try again but add <?php to the top of token.code.php
well, I have the following in my file... ``` <?php /** * Comment here */ $first_array = array( 'key1' => 'val1', 'key2' => 'val2', 'key3' => 'val3', 'key4' => 'val4', 'key5' => 'val5' ); $second_array = array( 'key1' => 'val1', 'key2' => 'val2' ); ``` And I get nothing
I think when he says "multi-line array/string" he means an array definition that spans multiple lines, not array values that span multiple lines. But a PHP parser to parse PHP is definitely the way to go.
Yes. True. Sorry for not responding quicker @Scuzzy. I was editing the OP for further clarification
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.