Replace string read from a file

Asked

Viewed 36 times

0

I’m creating a routine using the Symfony console to create new controllers from a pre-existing template file, but when searching for pattern defined in this template, the class SplFileObject jumps and sometimes skips a few lines;

public function writeWithTemplate($template)
{
    try {
        $this->template = new \SplFileObject(__DIR__ . "/templates/{$template}", "r");

        $pattern = '@' . strtoupper($template) . '@';

        while (!$this->template->eof()) {
            $this->file->fwrite($this->template->fgets());
        }
        return true;
    } catch(\Exception $error) {

        return false;
    }
}

the $this->file is also an open file using the SplFileObject, in this way that this function the same works perfectly, however if I make some comparisons within the while the write is not applied correctly.

the template file is:

<?php

namespace App\Controller;

use App\Controller\Controller;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;

class @CONTROLLER@ extends Controller
{

    public function main(Request $request, Response $response)
    {

    }
}

Note that there is a tag @CONTROLLER@ which is where I wish to do the substitution, if I do a check inside the while;

...
while (!$this->template->eof()) {
    if (strpos($this->template->fgets(), $pattern) !== false) {
       $line = str_replace($pattern, $this->fileName, $this->template->fgets());
    }         
    $line = empty($line) ? $this->template->fgets() : $line;
    $this->file->fwrite($line); 
}

Sometimes the generated file comes out only with } (1 or more) and several other meaningless combinations.

1 answer

3


You may have more problems with your code, but one obvious is this:

Here you take a line and see if the Pattern is on that line:

if (strpos($this->template->fgets(), $pattern) !== false) {
//                          ^^^^^ leu uma linha

but then you picks up a new line and try to change the Pattern in this new:

   $line = str_replace($pattern, $this->fileName, $this->template->fgets());
   //                                                              ^^^^^ leu outra

That is, you are discarding most of the lines with the Pattern, and trying to change the Pattern on some line that doesn’t know if it really needs.

More sense would make that:

$line = $this->template->fgets();
if (strpos($line , $pattern) !== false) {
    $line = str_replace($pattern, $this->fileName, $line );
}

Actually, you need to see if it’s justified to have the if. Supposing it wasn’t something to be executed all the time, that’s all it would take:

while (!$this->template->eof()) {
    $line = $this->template->fgets();
    if(!empty($line)) $this->file->fwrite(str_replace($pattern, $this->fileName, $line));
}

Like it or not, the strpos has some cost. It is slightly less than the str_replace, but most likely the gain does not compensate in this scenario (I imagine that your generated file is the cache for normal use, and you only consume the template when there is some change).

  • Got it right! Thanks! , the only thing I found strange is the question of fgets(), if I use 3x $this->template->fgets(); even inside the while I’ll pick up 3 lines at once? I thought catching the line was conditional on eof() and that it would be he who would determine on which line the pointer would be.

  • eof (Andnd Thef File) is used in while to know if you have reached the end of the file. Who picks up the line is the fgets. It is right that the staff will release the withdrawal of "fgets" in February, but it is not good to abuse the code :P

  • http://php.net/manual/en/splfileobject.fgets.php

  • Yes Bacco, I know what is eof, what I had in mind is that eof would work together with fgets to know on which line to put the pointer.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.