0

What is an efficient way to get the part of a string after the occurrence of a certain needle, only if that needle is at the start of the haystack. Similar to strstr(), but excluding the needle, and only when found at the beginning of the string.

If it isn't found, it should preferably return false.

I have the feeling I'm overlooking some very obvious PHP functions here, but I can't seem to think of them right now.

For example:

$basePath = '/some/dir/';

$result = some_function( '/some/dir/this/is/the/relative/part', $basePath );
/*
should return:
this/is/the/relative/part
*/

$result = some_function( '/fake/dir/this/is/the/relative/part', $basePath );
$result = some_function( '/pre/some/dir/this/is/the/relative/part', $basePath );
/*
last example has '/some/dir/' in it, but not at start.
should both preferably return:
false
*/

I'll be using this for a filesystem service that should act as a sandbox, and should be able to give out and take in paths, relative to the base sand box directory.

6 Answers 6

3

This case calls for strncmp:

function some_function($path, $base) {
    if (strncmp($path, $base, $n = strlen($base)) == 0) {
        return substr($path, $n);
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Yeah, I think this is the way to go. Thanks. Brad was a bit earlier with a very similar strncmp variant. But this one is a tad bit sleeker though. :D
1

Put more simply than the other examples:

function some_function($path,$base){
  $baselen = strlen($base);
  if (strpos($path,$base) === 0 && strlen($path)>$baselen)
    return substr($path,$baselen);
  return false;
}

DEMO

Alternate using strncmp, too: DEMO

5 Comments

I like the strncmp variant very much!
PS.: the strlen($path) > $baselen on the strncmp variant is redundant, no? Or am I overlooking something vital here?
@fireeyedboy: I added the check in case the path matches the base. You'll receive a false back saying, basically, "i have no further information to grab".
Ah yes of course, clever! Although, in this case I don't mind it returning an empty string. As this would be a valid relative path. Good thinking though. Much brighter than I am today. :)
About your strncasecomp() remark. Good point! But seeing I'm dense today, I'll have to ponder on the implications of this first, before commenting any more. :) Thanks so far!
1
function some_function($haystack, $baseNeedle) {
   if (! preg_match('/^' . preg_quote($baseNeedle, '/') . '(.*)$/', $haystack, $matches)) {
      return false;
   }
   return $matches[1];
}

Comments

0
function some_function($path, $basePath) {
    $pos = strpos($path, $basePath);
    if ($pos !== false) {
        return substr($path, strlen($basePath));
    } else {
        return false;
    }
}

But what about this?

some_function('/base/path/../../secret/password.txt', '/base/path/safe/dir/');

You likely want to call realpath() on $path first, so that it is fully simplified, before using some_function().

6 Comments

Good point about realpath(), but I'm using that already actually. Thanks!
@fireeyedboy: Though it's really on valid in a *nix environment. ;-) (Unless you switch to strncasecmp)
@Brad: not sure I follow you. Sorry, I'm a bit dense today. Do you mean to say realpath() is only valid on *nix? Because of case sensitivity perhaps?
@fireeyedboy: Actually, I'm the one slipping. :grin: The answers [min & erisco] were right below each other. I saw your reply to my answer and though I was replying back in the same post. D'oh! My original comment was in regards to *nix being case sensitive with paths (your reference to strncmp and my reply with strncasecmp). My apologies for the confusion.
@erisco: if ($pos !== false) should actually be if ($pos === 0) in my case, because it should only be valid if the needle is found at the start of the haystack.
|
0

Not sure if there's a built-in function for this.

function some_function($str1, $str2) {
  $l = strlen($str2);
  if (substr($str1, 0, $l) == $str2)
    return substr($str1, $l);
  else
    return false;
}

For long $str1 and short $str2, I think this is going to be faster than using strpos.

If you're using this for paths, you might want to do some checking if the slashes are at the right place.

Comments

0

How about regular expressions?

$regexp = preg_quote($basepath, '/');
return preg_replace("/^$regexp/", "", $path);

Comments

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.