MoFish Posted August 13, 2015 Share Posted August 13, 2015 Hi, I'm having a bit of bother doing a bit of string manipulation. I have the following HTML in a variable called $data <div class="text"> <mofish id="testing" type="testing" title="true" /> </div> I'm trying to replace the <mofish id="text" type="text" title="true" /> part with a value, for example the word "Hello". However, I dont want to have to hard code into the string replace the attribute values, as these could potentially change. Ideally I would like it to do a string replace on the start of the <mofish tag until the closing tag /> without taking into consideration any of the attributes. I have tried using str_replace but think i'm maybe off tangent? Would this be a regex job? Any guidance much appriciated. Thanks, MoFish Quote Link to comment Share on other sites More sharing options...
Barand Posted August 13, 2015 Share Posted August 13, 2015 like this? $str = '<div class="text"> <mofish id="testing" type="testing" title="true" /> </div>'; $replace = 'whatever'; $p1 = strpos($str, '<mofish'); $p2 = strpos($str, '/>', $p1); $str = substr_replace($str, $replace, $p1+8, $p2-($p1+9)); 2 Quote Link to comment Share on other sites More sharing options...
akphidelt2007 Posted August 14, 2015 Share Posted August 14, 2015 (edited) You can work this through preg_replace... $str = '<div class="text"> <mofish id="testing" type="testing" title="true" /> </div>'; $pattern = '/<mofish[^>]*>/'; $replace = 'whatever'; $newString = preg_replace($pattern , $replace , $str); Edited August 14, 2015 by akphidelt2007 Quote Link to comment Share on other sites More sharing options...
Barand Posted August 14, 2015 Share Posted August 14, 2015 My method, using strpos, produces <div class="text"><mofish whatever /></div> The preg_replace method takes twice as long and produces <div class="text">whatever</div> Quote Link to comment Share on other sites More sharing options...
MoFish Posted August 18, 2015 Author Share Posted August 18, 2015 (edited) Hi, Thanks for your replies and appologies in being a bit slow coming back to you. akphidelt2007s answer done exactly as required, as i only required the 'whatever' value to be returned. Thank you! I do however need to amend the pattern slightly, so it only gets mofish tags with specific ids. For example say i only wanted to run the preg_replace where id = 'number2' $str = '<div class="text"> <mofish id="number1" type="number1" title="true" /> </div> <div class="text"> <mofish id="number2" type="number2" title="true" /> </div>'; Regards, MoFish Edited August 18, 2015 by MoFish Quote Link to comment Share on other sites More sharing options...
Barand Posted August 18, 2015 Share Posted August 18, 2015 try $str = '<div class="text"> <mofish id="number1" type="number1" title="true" /> </div> <div class="text"> <mofish id="number2" type="number2" title="true" /> </div>'; $replace = 'whatever'; $p2=0; while(($p1 = strpos($str, '<mofish', $p2)) !== false) { $p2 = strpos($str, '/>', $p1); $x = (substr($str,$p1,$p2-$p1+2)); if (strpos($x, 'id="number2"')) { break; } } $newstr = str_replace($x, $replace, $str); Quote Link to comment Share on other sites More sharing options...
MoFish Posted August 18, 2015 Author Share Posted August 18, 2015 (edited) Thanks so much Barand, that appears to be doing everything for the time being. No doubt i'll get stuck again sometime soon! Thanks, MoFish Edited August 18, 2015 by MoFish Quote Link to comment Share on other sites More sharing options...
MoFish Posted August 18, 2015 Author Share Posted August 18, 2015 Hi Barand, Found a slight problem. If you put in an ID that doesnt exist, it still does the replace. Is there anyway to just return blank if its not found? $str = '<div class="col-xs-3 text-center"> <h4><mofish id="number33" type="text" label="Title" /></h4> <p><mofish id="number25" type="text" label="Description" /></p> </div>'; $replace = 'whatever'; $p2=0; while(($p1 = strpos($str, '<mofish', $p2)) !== false) { $p2 = strpos($str, '/>', $p1); $x = (substr($str,$p1,$p2-$p1+2)); if (strpos($x, 'id="number2"')) { break; } } $newstr = str_replace($x, $replace, $str); echo $newstr; Quote Link to comment Share on other sites More sharing options...
Barand Posted August 18, 2015 Share Posted August 18, 2015 $p2=0; $found = 0; while(($p1 = strpos($str, '<mofish', $p2)) !== false) { $p2 = strpos($str, '/>', $p1); $x = (substr($str,$p1,$p2-$p1+2)); if (strpos($x, 'id="number2"')) { $found = 1; break; } } if ($found) { $newstr = str_replace($x, $replace, $str); } 1 Quote Link to comment Share on other sites More sharing options...
MoFish Posted August 18, 2015 Author Share Posted August 18, 2015 Cheers! That done the trick! Quote Link to comment Share on other sites More sharing options...
MoFish Posted August 20, 2015 Author Share Posted August 20, 2015 Hi Barand,If you don't mind, I have one more issue I have come across which relates to the code you helped me with.This if probably something simple I've done, however would appreciate it if you could lend a helping hand, as have been looking at it for a while now.I have amended the code so that results are coming from a database which seems to be working good to a certain degree...However the results I am getting back are not quite as I expected. Please see the example below: <?php public function run (){ $str = '<div class="col-xs-3 text-center"> <h4><mofish id="template1" type="text" label="Title" /></h4> <p><mofish id="template2" type="text" label="Description" /></p> </div>'; // for each row in database foreach($result as $row){ // set replacement to be the string from db $replace = $row['string']; $p2=0; $found = 0; while(($p1 = strpos($str, '<mofish', $p2)) !== false) { $p2 = strpos($str, '/>', $p1); $x = (substr($str,$p1,$p2-$p1+2)); // template contains template1 or template2 if (strpos($x, 'id="'.$row['template'].'"')) { $found = 1; break; } } if ($found) { $newstr = str_replace($x, $replace, $str); } // i think i need to concatenate these somehow echo $newstr; // return $newstr; } } ?> I am getting results returning to the browser, however it seems to be taking it in turns for each instance. I had hoped it would have done both replacements in each instance. <div class="col-xs-3 text-center"> <h4>PHP Freaks</h4> <p><mofish id="template2" type="text" label="Description" /></p> </div> <div class="col-xs-3 text-center"> <h4><mofish id="template1" type="text" label="Title" /></h4> <p>This is a question</p> </div> Expected <div class="col-xs-3 text-center"> <h4>PHP Freaks</h4> <p>This is a question</p> </div> <div class="col-xs-3 text-center"> <h4>Another One</h4> <p>This is a question</p> </div> It is probably something to do with the way I'm echoing them, and possibly need to be concatenating the results together then returning it as one string? Would that be correct? Hope this makes sense, MoFish Quote Link to comment Share on other sites More sharing options...
Barand Posted August 20, 2015 Share Posted August 20, 2015 try putting the replacement code in a separate function then call it for each row // array to simulate db results $result = [ ['string'=>'replacement 1', 'template'=>'template1'], ['string'=>'replacement 2', 'template'=>'template2'], ]; $str = '<div class="col-xs-3 text-center"> <h4><mofish id="template1" type="text" label="Title" /></h4> <p><mofish id="template2" type="text" label="Description" /></p> </div>'; // for each row in database foreach($result as $row){ // set replacement to be the string from db $replace = $row['string']; $srch = $row['template']; $str = replace_mofish($srch, $replace, $str); } echo '<pre>',htmlentities($str),'</pre>'; // check output function replace_mofish($srch, $replace, $str) { $p2=0; $found = 0; while(($p1 = strpos($str, '<mofish', $p2)) !== false) { $p2 = strpos($str, '/>', $p1); $x = (substr($str,$p1,$p2-$p1+2)); // template contains template1 or template2 if (strpos($x, "id=\"$srch\"")) { $found = 1; break; } } if ($found) { return str_replace($x, $replace, $str); } else return $str; } gives <div class="col-xs-3 text-center"> <h4>replacement 1</h4> <p>replacement 2</p> </div> Quote Link to comment Share on other sites More sharing options...
MoFish Posted August 20, 2015 Author Share Posted August 20, 2015 Hi Barand, I managed to get your code working, however my $result array from the database returns slightly differently than your example. Mine has keys, which i think is breaking things slightly. Array ( [0] => Array ( [blah] => 41 ) [1] => Array ( [blah] => 42 ) ) Quote Link to comment Share on other sites More sharing options...
Barand Posted August 20, 2015 Share Posted August 20, 2015 All arrays have keys $result = [ ['string'=>'replacement 1', 'template'=>'template1'], ['string'=>'replacement 2', 'template'=>'template2'], ]; echo '<pre>',print_r($result, true),'</pre>'; gives Array ( [0] => Array ( [string] => replacement 1 [template] => template1 ) [1] => Array ( [string] => replacement 2 [template] => template2 ) ) Quote Link to comment Share on other sites More sharing options...
MoFish Posted August 21, 2015 Author Share Posted August 21, 2015 HI Barand, When used your example code, both replacements worked well. Once changing to the DB it only seems to be doing one for some reason. <div class="col-xs-3 text-center"> <h4><mofish id="title" type="text" label="Title" /></h4> <p>Once upon a time...</p></div> Below is the two functions you helped with. I've amended things slightly but not to drastically. public function area($name){ $query = "SELECT areas_content.*, areas.* FROM areas_content INNER JOIN areas ON areas.id = areas_content.area_id WHERE area_id = '41' "; $this->database->sql($query); $result = $this->database->getResult(); echo "<pre>"; print_r($result); echo "</pre>"; foreach($result as $row){ // set replacement to be the string from db $str = file_get_contents("templates/staff.html", true); $replace = $row['content']; $srch = $row['location']; $str = $this->replace($srch, $replace, $str); } echo '<pre>',htmlentities($str),'</pre>'; // check output } public function replace($srch, $replace, $str) { $p2=0; $found = 0; while(($p1 = strpos($str, '<mofish', $p2)) !== false) { $p2 = strpos($str, '/>', $p1); $x = (substr($str,$p1,$p2-$p1+2)); // template contains template1 or template2 if (strpos($x, "id=\"$srch\"")) { $found = 1; break; } } if ($found) { return str_replace($x, $replace, $str); } else return $str; } And the array output Array ( [0] => Array ( [id] => 41 [content] => Hello world [area_id] => 41 [location] => title [name] => Staff [template] => staff => Home ) [1] => Array ( [id] => 41 [content] => Once upon a time... [area_id] => 41 [location] => description [name] => Staff [template] => staff => Home ) ) And inside staff.html <div class="col-xs-3 text-center"> <h4><mofish id="title" type="text" label="Title" /></h4> <p><mofish id="description" type="text" label="Description" /></p> </div> Quote Link to comment Share on other sites More sharing options...
Barand Posted August 21, 2015 Share Posted August 21, 2015 this line $str = file_get_contents("templates/staff.html", true); needs to be before the loop otherwise you reset the content each time Quote Link to comment Share on other sites More sharing options...
MoFish Posted August 22, 2015 Author Share Posted August 22, 2015 (edited) Morning Barand, You are correct in that moving the get file contents outside of the loop resolved the populating of data. I moved it inside the loop as wanted to get the location from the DB from the 'template' field, like the following. foreach($result as $row){ $str = file_get_contents("templates/".$row['template'].".html", true); I'm assuming from your response above, this technique would not work? Thanks. Edited August 22, 2015 by MoFish Quote Link to comment Share on other sites More sharing options...
Barand Posted August 22, 2015 Share Posted August 22, 2015 $str = file_get_contents("templates/".$row['template'].".html", true); That is not what the code you posted shows. We cannot help with your code if you post something different from what you are really doing. Quote Link to comment Share on other sites More sharing options...
MoFish Posted August 22, 2015 Author Share Posted August 22, 2015 Hi Barand, No problem, i'll try to figure it out. I appriciate all the help you have gave me thus far. Regards, MoFish Quote Link to comment Share on other sites More sharing options...
Barand Posted August 22, 2015 Share Posted August 22, 2015 You need to save the changes so you do not reset the input each time foreach($result as $row){ // set replacement to be the string from db $str = file_get_contents("templates/staff.html", true); $replace = $row['content']; $srch = $row['location']; $str = $this->replace($srch, $replace, $str); file_put_contents("templates/staff.html", $str); // ADD } Quote Link to comment Share on other sites More sharing options...
MoFish Posted August 26, 2015 Author Share Posted August 26, 2015 Hi Barand, I didn't really want to save back to the file ideally... I'll see if I can find an alternative. Thanks, MoFish Quote Link to comment Share on other sites More sharing options...
Barand Posted August 26, 2015 Share Posted August 26, 2015 An alternative would be only to get the file contents when there is a new id value $prevID = ''; foreach($result as $row){ // set replacement to be the string from db if ($row['id'] != $prevID { $str = file_get_contents("templates/staff.html", true); $prevID = $row['id']; } $replace = $row['content']; $srch = $row['location']; $str = $this->replace($srch, $replace, $str); } Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.