I am beginner php developer. I need found values in my string (post code).
I make this code:
private function findPostCode(string $string): array|null
{
preg_match("(\b\d{2}\s*-\d{3}\b)", $string, $matches);
if($matches){
return $matches;
}
if(!$matches){
preg_match("(\b\d{2}\s*\d{3}\b)", $string, $matches);
return $matches;
}
return null;
}
When i have string: '99888 city street' or '99-888 city street' - it's work fine.
I have array with my results.
Problem is when i have more post code: '99888 12-230 city street 98-234'.
I have always one results.
How can i repair it?
Please help me
In your code preg_match() function find only first matches.
You need to use preg_match_all() function for find all possible matches.
Your solution code looks like :
private function findPostCode(string $string): array|null
{
$matches = array();
preg_match_all("(\b\d{2}\s*-\d{3}\b|\b\d{2}\s*\d{3}\b)", $string, $matches);
if(count($matches[0]) > 0){
return $matches[0];
}
return null;
}
Related
I am using preg_match to verify an input :
$string = 'test';
if (preg_match ('/[^-a-z\d]/i', $string))
{
return true;
}
else
{
return false;
}
Well I can not understand why it return false here !
Am I missing something ?
Shouldn't it return true ?
The solution :
(preg_match ('/^[-a-z\d]*$/i', $string))
Tyr this
(preg_match ('/^[-A-Za-z\d]*$/', $string))
So preg_match() can return 0, 1, or false it is probably safer to do a strict check that the result equals 1, i.e.
abstract class Pattern
{
/** #const int */
const TEXT_MATCH = 1;
/**
* #param string $pattern regex pattern to match against
* #param string $string the text string to search
*
* #return bool
*/
public static function match(string $pattern, string $string): bool
{
return preg_match($pattern, $string) === self::TEXT_MATCH;
}
}
Primarily the bit you're interested in is this
preg_match($pattern, $string) === 1;
If you then use it:
$result = Pattern::match('/[^-a-z\d]/i', 'test');
var_dump($result); // false
The string doesn't pass the check. If that doesn't resolve your issue we're going to need to see a few examples of strings you are passing through that are always passing. It's probably also worth explaining what you want the regex to match against, because that could be part of the issue also.
Previously I have been echoing $obj->html but a current project requires that the HTML be examined for slugs like {whatever} and replacing these with other content.
I have two problems. The first is that this code is slower than I would like:
class Foo {
function draw_content() {
$slug = "/(?<=\{).*(?=\})/";
if (preg_match($slug, $this->html, $matches)) {
foreach ($matches as $match) {
if (method_exists($this,$match)) {
$replacement = $this->$match();
$this->html = preg_replace("/\{$match\}/", $replacement, $this->html);
}
}
}
return $this->html;
} // fn
function new_releases() {
echo "new release book covers";
} // fn
} // class
Is there a better way to get the slug contents? I presume the regex is what is slowing this down?
The second issue is stranger to me. Given this $obj->html:
<p class="headline">New Releases</p>
<p>xxx{new_releases}xxxx</p>
The processed output of $obj->draw_content() is drawn by <?=$obj->draw_content()?>
new release book covers<p class="headline">New Releases</p>
<p>xxxxxxx</p>
Why is the new_releases() output prepended? The slug is gone but the replacement is not in it's place!
you can replace your pattern by:
$slug = '~{\K[^}]*+(?=})~';
IMHO, you should replace your preg_match test and your preg_replace by an only preg_replace_callback function, try something like this (and correct the bugs :).
function draw_content() {
$slug = '~{([^}]*+)}~';
$that = $this;
$this->html = preg_replace_callback( $slug, function ($m) use ($that) {
if (method_exists($that, $m[1]))
return $that->$m[1]();
return $m[0]; }, $this->html);
return $this->html;
}
i have a problem with insensitive array_keys and in_array ...
I developing a translator, and i have something like this:
$wordsExample = array("example1","example2","example3","August","example4");
$translateExample = array("ejemplo1","ejemplo2","ejemplo3","Agosto","ejemplo4");
function foo($string,$strict=FALSE)
{
$key = array_keys($wordsExample,$string,$strict);
if(!empty($key))
return $translateExample[$key[0]];
return false;
}
echo foo('example1'); // works, prints "ejemplo1"
echo foo('august'); // doesnt works, prints FALSE
I tested with in_array and same result...:
function foo($string,$strict=FALSE)
{
if(in_array($string,$wordsExample,$strict))
return "WOHOOOOO";
return false;
}
echo foo('example1'); //works , prints "WOHOOOOO"
echo foo('august'); //doesnt works, prints FALSE
Create the array and find the keys with with strtolower:
$wordsExample = array("example1","example2","example3","August","example4");
$lowercaseWordsExample = array();
foreach ($wordsExample as $val) {
$lowercaseWordsExample[] = strtolower($val);
}
if(in_array(strtolower('august'),$lowercaseWordsExample,FALSE))
return "WOHOOOOO";
if(in_array(strtolower('aUguSt'),$lowercaseWordsExample,FALSE))
return "WOHOOOOO";
Another way would be to write a new in_array function that would be case insensitive:
function in_arrayi($needle, $haystack) {
return in_array(strtolower($needle), array_map('strtolower', $haystack));
}
If you want it to use less memory, better create the words array using lowercase letter.
I created a small function a while to get, to test clean-URLs as they could be uppercase, lowercase or mixed:
function in_arrayi($needle, array $haystack) {
return in_array(strtolower($needle), array_map('strtolower', $haystack));
}
Pretty easy this way.
I'm trying to use Mustache together with i18n (php, within Wordpress). I've got the basic __ functionality working nicely, something like this
class my_i18n {
public function __trans($string) {
return __($string, 'theme-name');
}
}
class mytache {
public function __()
{
return array('my_i18n', '__trans');
}
}
Then to output a template with an i18n string, I can simply do this
$context = new mytache;
$template = "<div>{{#__}}String to translate{{/__}}</div>";
$m = new Mustache;
echo $m->render($template, $context);
So far everything is fine. However, I want to be able to translate strings with parameters. i.e. the equivalent of sprint_f(__('Account Balance: %s'), $balance);.
It seems that if I do something like {{#__}}Account Balance: {{balance}}{{/__}} it doesn't work. I'm guessing because the inner tag gets converted first and therefore the translation cannot be found for the phrase.
Any ideas how to achieve this cleanly with Mustache?
UPDATE: here's the end-result snippet (with massive help from bobthecow):
class I18nMapper {
public static function translate($str) {
$matches = array();
// searching for all {{tags}} in the string
if (preg_match_all('/{{\s*.*?\s*}}/',$str, &$matches)) {
// first we remove ALL tags and replace with %s and retrieve the translated version
$result = __(preg_replace('/{{\s*.*?\s*}}/','%s', $str), 'theme-name');
// then replace %s back to {{tag}} with the matches
return vsprintf($result, $matches[0]);
}
else
return __($str, 'theme-name');
}
}
class mytache {
public function __()
{
return array('I18nMapper', 'trans');
}
}
I added an i18n example here... it's pretty cheesy, but the test passes. It looks like that's almost the same as what you're doing. Is it possible that you're using an outdated version of Mustache? The spec used to specify different variable interpolation rules, which would make this use case not work as expected.
On my behalf I would suggest using normal, fully functional template engine. I understand, that small is great and everything, but for example Twig is much more advanced. So I would recommend it.
About mustache. Can't you just extend you translation method! For example you pass {{#__}}Account Balance: #balance#{{/__}}
function __( $string, $replacement )
{
$replaceWith = '';
if ( 'balance' == $replacement )
{
$replaceWith = 234.56;
}
return str_replace( '#' . $replacement . '#', $replaceWith, $string );
}
class my_i18n
{
public function __trans( $string )
{
$matches = array();
$replacement = '';
preg_match( '~(\#[a-zA-Z0-9]+\#)~', $string, $matches );
if ( ! empty( $matches ) )
{
$replacement = trim( $matches[0], '#' );
}
return __( $string, $replacement );
}
}
$Mustache = new Mustache();
$template = '{{#__}}Some lime #tag#{{/__}}';
$MyTache = new mytache();
echo $Mustache->render( $template, $MyTache );
This is a very ugly example, but you can make it fancy yourself. As I see Mustache on it's own will not be able to do what you want.
Hope that helped.
Pretty straightforward; I can't seem to find anything definitive regarding PHP's preg_replace() supporting named backreferences:
// should match, replace, and output: user/profile/foo
$string = 'user/foo';
echo preg_replace('#^user/(?P<id>[^/]+)$#Di', 'user/profile/(?P=id)', $string);
This is a trivial example, but I'm wondering if this syntax, (?P=name) is simply not supported. Syntactical issue, or non-existent functionality?
They exist:
http://www.php.net/manual/en/regexp.reference.back-references.php
With preg_replace_callback:
function my_replace($matches) {
return '/user/profile/' . $matches['id'];
}
$newandimproved = preg_replace_callback('#^user/(?P<id>[^/]+)$#Di', 'my_replace', $string);
Or even quicker
$newandimproved = preg_replace('#^user/([^/]+)$#Di', '/user/profile/$1', $string);
preg_replace does not support named backreferences.
preg_replace_callback supports named backreferences, but after PHP 5.3, so expect it to fail on PHP 5.2 and below.
preg_replace does not supported named subpatterns yet.
you can use this :
class oreg_replace_helper {
const REGEXP = '~
(?<!\x5C)(\x5C\x5C)*+
(?:
(?:
\x5C(?P<num>\d++)
)
|
(?:
\$\+?{(?P<name1>\w++)}
)
|
(?:
\x5Cg\<(?P<name2>\w++)\>
)
)?
~xs';
protected $replace;
protected $matches;
public function __construct($replace) {
$this->replace = $replace;
}
public function replace($matches) {
var_dump($matches);
$this->matches = $matches;
return preg_replace_callback(self::REGEXP, array($this, 'map'), $this->replace);
}
public function map($matches) {
foreach (array('num', 'name1', 'name2') as $name) {
if (isset($this->matches[$matches[$name]])) {
return stripslashes($matches[1]) . $this->matches[$matches[$name]];
}
}
return stripslashes($matches[1]);
}
}
function oreg_replace($pattern, $replace, $subject) {
return preg_replace_callback($pattern, array(new oreg_replace_helper($replace), 'replace'), $subject);
}
then you can use either \g<name> ${name} or $+{name} as reference in your replace statement.
cf (http://www.rexegg.com/regex-disambiguation.html#namedcapture)