代码之家  ›  专栏  ›  技术社区  ›  Ali

PHP中的startswith()和endswith()函数

  •  1294
  • Ali  · 技术社区  · 16 年前

    如果一个字符串以指定的字符/字符串开头或以指定的字符/字符串结尾,我如何编写两个函数来获取该字符串并返回它?

    例如:

    $str = '|apples}';
    
    echo startsWith($str, '|'); //Returns true
    echo endsWith($str, '}'); //Returns true
    
    30 回复  |  直到 6 年前
        1
  •  1395
  •   MrHus    6 年前
    function startsWith($haystack, $needle)
    {
         $length = strlen($needle);
         return (substr($haystack, 0, $length) === $needle);
    }
    
    function endsWith($haystack, $needle)
    {
        $length = strlen($needle);
        if ($length == 0) {
            return true;
        }
    
        return (substr($haystack, -$length) === $needle);
    }
    

    如果不想使用regex,请使用此选项。

        2
  •  949
  •   vaxquis user2577497    6 年前

    可以使用 strrpos strpos 分别检查开头和结尾。

    注意使用 斯特罗斯 检查从和开始 斯特罗斯 to check ends with将尽快返回,而不是检查整个字符串直到结束。此外,此解决方案不会创建临时字符串。在投反对票之前考虑解释原因。仅仅因为dwtf的f-wit不理解这个函数是如何工作的,或者认为只有一个解决方案,并不意味着这个答案是错误的。

    function startsWith($haystack, $needle) {
        // search backwards starting from haystack length characters from the end
        return $needle === ''
          || strrpos($haystack, $needle, -strlen($haystack)) !== false;
    }
    
    function endsWith($haystack, $needle) {
        // search forward starting from end minus needle length characters
        if ($needle === '') {
            return true;
        }
        $diff = \strlen($haystack) - \strlen($needle);
        return $diff >= 0 && strpos($haystack, $needle, $diff) !== false;
    }
    

    测试和结果( compare with this ):

    startsWith('abcdef', 'ab') -> true
    startsWith('abcdef', 'cd') -> false
    startsWith('abcdef', 'ef') -> false
    startsWith('abcdef', '') -> true
    startsWith('', 'abcdef') -> false
    
    endsWith('abcdef', 'ab') -> false
    endsWith('abcdef', 'cd') -> false
    endsWith('abcdef', 'ef') -> true
    endsWith('abcdef', '') -> true
    endsWith('', 'abcdef') -> false
    

    注: strncmp substr_compare 函数将优于此函数。

        3
  •  222
  •   Артур Курицын    7 年前

    更新日期:2016年8月23日

    功能

    function substr_startswith($haystack, $needle) {
        return substr($haystack, 0, strlen($needle)) === $needle;
    }
    
    function preg_match_startswith($haystack, $needle) {
        return preg_match('~' . preg_quote($needle, '~') . '~A', $haystack) > 0;
    }
    
    function substr_compare_startswith($haystack, $needle) {
        return substr_compare($haystack, $needle, 0, strlen($needle)) === 0;
    }
    
    function strpos_startswith($haystack, $needle) {
        return strpos($haystack, $needle) === 0;
    }
    
    function strncmp_startswith($haystack, $needle) {
        return strncmp($haystack, $needle, strlen($needle)) === 0;
    }
    
    function strncmp_startswith2($haystack, $needle) {
        return $haystack[0] === $needle[0]
            ? strncmp($haystack, $needle, strlen($needle)) === 0
            : false;
    }
    

    测验

    echo 'generating tests';
    for($i = 0; $i < 100000; ++$i) {
        if($i % 2500 === 0) echo '.';
        $test_cases[] = [
            random_bytes(random_int(1, 7000)),
            random_bytes(random_int(1, 3000)),
        ];
    }
    echo "done!\n";
    
    
    $functions = ['substr_startswith', 'preg_match_startswith', 'substr_compare_startswith', 'strpos_startswith', 'strncmp_startswith', 'strncmp_startswith2'];
    $results = [];
    
    foreach($functions as $func) {
        $start = microtime(true);
        foreach($test_cases as $tc) {
            $func(...$tc);
        }
        $results[$func] = (microtime(true) - $start) * 1000;
    }
    
    asort($results);
    
    foreach($results as $func => $time) {
        echo "$func: " . number_format($time, 1) . " ms\n";
    }
    

    结果(php 7.0.9)

    (最快到最慢排序)

    strncmp_startswith2: 40.2 ms
    strncmp_startswith: 42.9 ms
    substr_compare_startswith: 44.5 ms
    substr_startswith: 48.4 ms
    strpos_startswith: 138.7 ms
    preg_match_startswith: 13,152.4 ms
    

    结果(php 5.3.29)

    (最快到最慢排序)

    strncmp_startswith2: 477.9 ms
    strpos_startswith: 522.1 ms
    strncmp_startswith: 617.1 ms
    substr_compare_startswith: 706.7 ms
    substr_startswith: 756.8 ms
    preg_match_startswith: 10,200.0 ms
    

    startswith_benchmark.php

        4
  •  130
  •   Ram Sharma    9 年前

    到目前为止,所有的答案似乎都在做大量不必要的工作, strlen calculations , string allocations (substr) 'strpos' 'stripos' 函数返回第一次出现的 $needle 在里面 $haystack :

    function startsWith($haystack,$needle,$case=true)
    {
        if ($case)
            return strpos($haystack, $needle, 0) === 0;
    
        return stripos($haystack, $needle, 0) === 0;
    }
    
    function endsWith($haystack,$needle,$case=true)
    {
        $expectedPosition = strlen($haystack) - strlen($needle);
    
        if ($case)
            return strrpos($haystack, $needle, 0) === $expectedPosition;
    
        return strripos($haystack, $needle, 0) === $expectedPosition;
    }
    
        5
  •  45
  •   Rubens Mariuzzo Salakar    11 年前
    function startsWith($haystack, $needle, $case = true) {
        if ($case) {
            return (strcmp(substr($haystack, 0, strlen($needle)), $needle) === 0);
        }
        return (strcasecmp(substr($haystack, 0, strlen($needle)), $needle) === 0);
    }
    
    function endsWith($haystack, $needle, $case = true) {
        if ($case) {
            return (strcmp(substr($haystack, strlen($haystack) - strlen($needle)), $needle) === 0);
        }
        return (strcasecmp(substr($haystack, strlen($haystack) - strlen($needle)), $needle) === 0);
    }
    

    学分 :

    Check if a string ends with another string

    Check if a string begins with another string

        6
  •  26
  •   Timo Tijhof avalkab    12 年前

    上面的regex函数,但是上面还建议了其他的调整:

     function startsWith($needle, $haystack) {
         return preg_match('/^' . preg_quote($needle, '/') . '/', $haystack);
     }
    
     function endsWith($needle, $haystack) {
         return preg_match('/' . preg_quote($needle, '/') . '$/', $haystack);
     }
    
        7
  •  21
  •   lepe    15 年前

    如果速度对你很重要,试试这个。(我相信这是最快的方法)

    仅适用于字符串,如果$haystack只有1个字符

    function startsWithChar($needle, $haystack)
    {
       return ($needle[0] === $haystack);
    }
    
    function endsWithChar($needle, $haystack)
    {
       return ($needle[strlen($needle) - 1] === $haystack);
    }
    
    $str='|apples}';
    echo startsWithChar($str,'|'); //Returns true
    echo endsWithChar($str,'}'); //Returns true
    echo startsWithChar($str,'='); //Returns false
    echo endsWithChar($str,'#'); //Returns false
    
        8
  •  20
  •   noamtm    6 年前

    这个问题已经有了许多答案,但在某些情况下,你可以解决一些比所有答案都简单的问题。 如果您要查找的字符串是已知的(硬编码),那么您可以使用正则表达式而不需要任何引号等。

    检查字符串是否以“abc”开头:

    preg_match('/^ABC/', $myString); // "^" here means beginning of string
    

    以“abc”结尾:

    preg_match('/ABC$/', $myString); // "$" here means end of string
    

    在我的简单示例中,我想检查字符串是否以斜线结尾:

    preg_match('#/$#', $myPath);   // Use "#" as delimiter instead of escaping slash
    

    优点:由于它非常短和简单,因此不必定义函数(例如 endsWith() )如上图所示。

    但同样地,这不是每个案例的解决方案,只是这个非常具体的解决方案。

        9
  •  16
  •   JaÍ¢ck    11 年前

    以下是两个不引入临时字符串的函数,当指针很大时,它可能很有用:

    function startsWith($haystack, $needle)
    {
        return strncmp($haystack, $needle, strlen($needle)) === 0;
    }
    
    function endsWith($haystack, $needle)
    {
        return $needle === '' || substr_compare($haystack, $needle, -strlen($needle)) === 0;
    }
    
        10
  •  15
  •   James Black    15 年前

    我知道这已经完成了,但你可能想看看 strncmp 因为它允许您将字符串的长度与之进行比较,所以:

    function startsWith($haystack, $needle, $case=true) {
        if ($case)
            return strncasecmp($haystack, $needle, strlen($needle)) == 0;
        else
            return strncmp($haystack, $needle, strlen($needle)) == 0;
    }    
    
        11
  •  10
  •   Bhavik Shah    8 年前

    你可以使用 strpos strrpos

    $bStartsWith = strpos($sHaystack, $sNeedle) == 0;
    $bEndsWith = strrpos($sHaystack, $sNeedle) == strlen($sHaystack)-strlen($sNeedle);
    
        12
  •  8
  •   Lucas Bustamante    6 年前

    最快的endsWith()解决方案:

    # Checks if a string ends in a string
    function endsWith($haystack, $needle) {
        return substr($haystack,-strlen($needle))===$needle;
    }
    

    基准:

    # This answer
    function endsWith($haystack, $needle) {
        return substr($haystack,-strlen($needle))===$needle;
    }
    
    # Accepted answer
    function endsWith2($haystack, $needle) {
        $length = strlen($needle);
    
        return $length === 0 ||
        (substr($haystack, -$length) === $needle);
    }
    
    # Second most-voted answer
    function endsWith3($haystack, $needle) {
        // search forward starting from end minus needle length characters
        if ($needle === '') {
            return true;
        }
        $diff = \strlen($haystack) - \strlen($needle);
        return $diff >= 0 && strpos($haystack, $needle, $diff) !== false;
    }
    
    # Regex answer
    function endsWith4($haystack, $needle) {
        return preg_match('/' . preg_quote($needle, '/') . '$/', $haystack);
    }
    
    function timedebug() {
        $test = 10000000;
    
        $time1 = microtime(true);
        for ($i=0; $i < $test; $i++) {
            $tmp = endsWith('TestShortcode', 'Shortcode');
        }
        $time2 = microtime(true);
        $result1 = $time2 - $time1;
    
        for ($i=0; $i < $test; $i++) {
            $tmp = endsWith2('TestShortcode', 'Shortcode');
        }
        $time3 = microtime(true);
        $result2 = $time3 - $time2;
    
        for ($i=0; $i < $test; $i++) {
            $tmp = endsWith3('TestShortcode', 'Shortcode');
        }
        $time4 = microtime(true);
        $result3 = $time4 - $time3;
    
        for ($i=0; $i < $test; $i++) {
            $tmp = endsWith4('TestShortcode', 'Shortcode');
        }
        $time5 = microtime(true);
        $result4 = $time5 - $time4;
    
        echo $test.'x endsWith: '.$result1.' seconds # This answer<br>';
        echo $test.'x endsWith2: '.$result4.' seconds # Accepted answer<br>';
        echo $test.'x endsWith3: '.$result2.' seconds # Second most voted answer<br>';
        echo $test.'x endsWith4: '.$result3.' seconds # Regex answer<br>';
        exit;
    }
    timedebug();
    

    基准结果:

    10000000x endsWith: 1.5760900974274 seconds # This answer
    10000000x endsWith2: 3.7102129459381 seconds # Accepted answer
    10000000x endsWith3: 1.8731069564819 seconds # Second most voted answer
    10000000x endsWith4: 2.1521229743958 seconds # Regex answer
    
        13
  •  7
  •   Dan    13 年前

    简单易懂的一行程序,没有正则表达式。

    startsWith()直接向前。

    function startsWith($haystack, $needle) {
       return (strpos($haystack, $needle) === 0);
    }
    

    endsWith()使用稍微花哨和缓慢的strRev():

    function endsWith($haystack, $needle) {
       return (strpos(strrev($haystack), strrev($needle)) === 0);
    }
    
        14
  •  6
  •   FrancescoMM    11 年前

    专注于startswith,如果您确定字符串不是空的,那么在比较之前,在第一个字符上添加一个测试,strlen等,会加快速度:

    function startswith5b($haystack, $needle) {
        return ($haystack{0}==$needle{0})?strncmp($haystack, $needle, strlen($needle)) === 0:FALSE;
    }
    

    它以某种方式更快(20%-30%)。添加另一个char测试,比如$haystack 1==$needle 1似乎不会加快速度,甚至可能会减慢速度。

    === 似乎比 == 条件运算符 (a)?b:c 似乎比 if(a) b; else c;


    对于那些问“为什么不使用strpos?”称其他解决方案为“不必要的工作”


    strpos速度很快,但它不是这个工作的合适工具。

    为了理解,这里有一个小的模拟例子:

    Search a12345678c inside bcdefga12345678xbbbbb.....bbbbba12345678c
    

    电脑在里面做什么?

        With strccmp, etc...
    
        is a===b? NO
        return false
    
    
    
        With strpos
    
        is a===b? NO -- iterating in haysack
        is a===c? NO
        is a===d? NO
        ....
        is a===g? NO
        is a===g? NO
        is a===a? YES
        is 1===1? YES -- iterating in needle
        is 2===3? YES
        is 4===4? YES
        ....
        is 8===8? YES
        is c===x? NO: oh God,
        is a===1? NO -- iterating in haysack again
        is a===2? NO
        is a===3? NO
        is a===4? NO
        ....
        is a===x? NO
        is a===b? NO
        is a===b? NO
        is a===b? NO
        is a===b? NO
        is a===b? NO
        is a===b? NO
        is a===b? NO
        ...
        ... may many times...
        ...
        is a===b? NO
        is a===a? YES -- iterating in needle again
        is 1===1? YES
        is 2===3? YES
        is 4===4? YES
        is 8===8? YES
        is c===c? YES YES YES I have found the same string! yay!
        was it at position 0? NOPE
        What you mean NO? So the string I found is useless? YEs.
        Damn.
        return false
    

    假设strlen不迭代整个字符串(但即使在这种情况下),这一点都不方便。

        15
  •  6
  •   yuvilio    10 年前

    我通常会去图书馆 underscore-php 这些天。

    require_once("vendor/autoload.php"); //use if needed
    use Underscore\Types\String; 
    
    $str = "there is a string";
    echo( String::startsWith($str, 'the') ); // 1
    echo( String::endsWith($str, 'ring')); // 1   
    

    这个图书馆有很多其他方便的功能。

        16
  •  6
  •   Veeno    8 年前

    这个 answer 通过 mpen 非常彻底,但不幸的是,提供的基准有一个非常重要和有害的监督。

    因为针和干草堆中的每一个字节都是完全随机的,所以针和干草堆对在第一个字节上不同的概率是99.609375%,这意味着100000对中平均有99609对在第一个字节上不同。换言之,该基准严重偏向于 startswith 显式检查第一个字节的实现,如 strncmp_startswith2 做。

    如果测试生成循环的实现方式如下:

    echo 'generating tests';
    for($i = 0; $i < 100000; ++$i) {
        if($i % 2500 === 0) echo '.';
    
        $haystack_length = random_int(1, 7000);
        $haystack = random_bytes($haystack_length);
    
        $needle_length = random_int(1, 3000);
        $overlap_length = min(random_int(0, $needle_length), $haystack_length);
        $needle = ($needle_length > $overlap_length) ?
            substr($haystack, 0, $overlap_length) . random_bytes($needle_length - $overlap_length) :
            substr($haystack, 0, $needle_length);
    
        $test_cases[] = [$haystack, $needle];
    }
    echo " done!<br />";
    

    基准测试结果的情况略有不同:

    strncmp_startswith: 223.0 ms
    substr_startswith: 228.0 ms
    substr_compare_startswith: 238.0 ms
    strncmp_startswith2: 253.0 ms
    strpos_startswith: 349.0 ms
    preg_match_startswith: 20,828.7 ms
    

    当然,这个基准可能仍然不是完全公正的,但是当给定部分匹配的指针时,它也会测试算法的效率。

        17
  •  6
  •   Vahid Amiri    7 年前

    下面是接受答案的多字节安全版本,适用于UTF-8字符串:

    function startsWith($haystack, $needle)
    {
        $length = mb_substr($needle, 'UTF-8');
        return (mb_substr($haystack, 0, $length, 'UTF-8') === $needle);
    }
    
    function endsWith($haystack, $needle)
    {
        $length = mb_strlen($needle, 'UTF-8');
        return $length === 0 ||
            (mb_substr($haystack, -$length, $length, 'UTF-8') === $needle);
    }
    
        18
  •  5
  •   Srinivasan.S    11 年前

    我希望下面的答案既有效又简单:

    $content = "The main string to search";
    $search = "T";
    //For compare the begining string with case insensitive. 
    if(stripos($content, $search) === 0) echo 'Yes';
    else echo 'No';
    
    //For compare the begining string with case sensitive. 
    if(strpos($content, $search) === 0) echo 'Yes';
    else echo 'No';
    
    //For compare the ending string with case insensitive. 
    if(stripos(strrev($content), strrev($search)) === 0) echo 'Yes';
    else echo 'No';
    
    //For compare the ending string with case sensitive. 
    if(strpos(strrev($content), strrev($search)) === 0) echo 'Yes';
    else echo 'No';
    
        19
  •  4
  •   biziclop    13 年前

    这个 substr 函数可以返回 false 在许多特殊情况下,下面是我的版本,它处理这些问题:

    function startsWith( $haystack, $needle ){
      return $needle === ''.substr( $haystack, 0, strlen( $needle )); // substr's false => empty string
    }
    
    function endsWith( $haystack, $needle ){
      $len = strlen( $needle );
      return $needle === ''.substr( $haystack, -$len, $len ); // ! len=0
    }
    

    试验(试验) true “好”意味着:

    var_dump( startsWith('',''));
    var_dump( startsWith('1',''));
    var_dump(!startsWith('','1'));
    var_dump( startsWith('1','1'));
    var_dump( startsWith('1234','12'));
    var_dump(!startsWith('1234','34'));
    var_dump(!startsWith('12','1234'));
    var_dump(!startsWith('34','1234'));
    var_dump('---');
    var_dump( endsWith('',''));
    var_dump( endsWith('1',''));
    var_dump(!endsWith('','1'));
    var_dump( endsWith('1','1'));
    var_dump(!endsWith('1234','12'));
    var_dump( endsWith('1234','34'));
    var_dump(!endsWith('12','1234'));
    var_dump(!endsWith('34','1234'));
    

    此外, substr_compare 功能也值得一看。 http://www.php.net/manual/en/function.substr-compare.php

        20
  •  4
  •   Vincent Pazeller    13 年前

    简而言之:

    function startsWith($str, $needle){
       return substr($str, 0, strlen($needle)) === $needle;
    }
    
    function endsWith($str, $needle){
       $length = strlen($needle);
       return !$length || substr($str, - $length) === $needle;
    }
    
        21
  •  3
  •   Community CDub    7 年前

    这可能起作用

    function startsWith($haystack, $needle) {
         return substr($haystack, 0, strlen($needle)) == $needle;
    }
    

    来源: https://stackoverflow.com/a/4419658

        22
  •  3
  •   Peter Mortensen icecrime    11 年前

    为什么不下面的内容?

    //How to check if a string begins with another string
    $haystack = "valuehaystack";
    $needle = "value";
    if (strpos($haystack, $needle) === 0){
        echo "Found " . $needle . " at the beginning of " . $haystack . "!";
    }
    

    输出:

    在valuehaystack的开头找到值!

    记住, strpos 如果在干草堆中没有找到针,将返回FALSE;如果并且仅当在索引0(即开始)找到针,将返回0。

    以下是结尾:

    $haystack = "valuehaystack";
    $needle = "haystack";
    
    //If index of the needle plus the length of the needle is the same length as the entire haystack.
    if (strpos($haystack, $needle) + strlen($needle) === strlen($haystack)){
        echo "Found " . $needle . " at the end of " . $haystack . "!";
    }
    

    在这种情况下,不需要函数startswith()作为

    (strpos($stringToSearch, $doesItStartWithThis) === 0)
    

    将准确返回真或假。

    奇怪的是,这里所有的疯狂功能都很简单。

        23
  •  3
  •   Jelle Keizer    10 年前

    我想这样做

         function startWith($haystack,$needle){
                  if(substr($haystack,0, strlen($needle))===$needle)
                  return true;
            }
    
      function endWith($haystack,$needle){
                  if(substr($haystack, -strlen($needle))===$needle)
                  return true;
            }
    
        24
  •  3
  •   dkellner    6 年前

    只是一个建议:

    function startsWith($haystack,$needle) {
        if($needle==="") return true;
        if($haystack[0]<>$needle[0]) return false;
        if(substr_compare($haystack,$needle,0,strlen($needle))==0) return true;
        return false;
    }
    

    另外一行比较字符串的第一个字符,可以使 错误案例返回 立即 因此,进行许多比较 更快(我测量时快了7倍)。在真实的情况下,你几乎不需要为这一行付出任何代价,所以我认为这是值得包括在内的。(此外,在实践中,当您为特定的起始块测试多个字符串时,大多数比较都会失败,因为在典型情况下,您正在寻找某些内容。)

        25
  •  2
  •   bobo    15 年前

    根据詹姆斯·布莱克的回答,以下是它的结尾版本:

    function startsWith($haystack, $needle, $case=true) {
        if ($case)
            return strncmp($haystack, $needle, strlen($needle)) == 0;
        else
            return strncasecmp($haystack, $needle, strlen($needle)) == 0;
    }
    
    function endsWith($haystack, $needle, $case=true) {
         return startsWith(strrev($haystack),strrev($needle),$case);
    
    }
    

    注意:我已经将if-else部分替换为james black的startswith函数,因为strncasecmp实际上是strncmp的不区分大小写版本。

        26
  •  2
  •   Freeman    14 年前

    还可以使用正则表达式:

    function endsWith($haystack, $needle, $case=true) {
      return preg_match("/.*{$needle}$/" . (($case) ? "" : "i"), $haystack);
    }
    
        27
  •  2
  •   womplefrog    10 年前

    以前的许多答案也同样有效。然而,这可能是尽可能短的,你可以让它做你想做的。你只需声明你希望它“返回真的”。所以我已经包含了返回布尔真/假和文本真/假的解决方案。

    // boolean true/false
    function startsWith($haystack, $needle)
    {
        return strpos($haystack, $needle) === 0 ? 1 : 0;
    }
    
    function endsWith($haystack, $needle)
    {
        return stripos($haystack, $needle) === 0 ? 1 : 0;
    }
    
    
    // textual true/false
    function startsWith($haystack, $needle)
    {
        return strpos($haystack, $needle) === 0 ? 'true' : 'false';
    }
    
    function endsWith($haystack, $needle)
    {
        return stripos($haystack, $needle) === 0 ? 'true' : 'false';
    }
    
        28
  •  1
  •   Patrick Smith    10 年前

    这里是针对php 4的有效解决方案。如果在php 5上使用 substr_compare 而不是 strcasecmp(substr(...)) .

    function stringBeginsWith($haystack, $beginning, $caseInsensitivity = false)
    {
        if ($caseInsensitivity)
            return strncasecmp($haystack, $beginning, strlen($beginning)) === 0;
        else
            return strncmp($haystack, $beginning, strlen($beginning)) === 0;
    }
    
    function stringEndsWith($haystack, $ending, $caseInsensitivity = false)
    {
        if ($caseInsensitivity)
            return strcasecmp(substr($haystack, strlen($haystack) - strlen($ending)), $haystack) === 0;
        else
            return strpos($haystack, $ending, strlen($haystack) - strlen($ending)) !== false;
    }
    
        29
  •  -1
  •   ymakux    7 年前
    $ends_with = strrchr($text, '.'); // Ends with dot
    $start_with = (0 === strpos($text, '.')); // Starts with dot
    
        30
  •  -3
  •   Spoo    8 年前

    不知道为什么这对人们来说如此困难。SUBSTR做得很好,而且效率很高,因为如果字符串不匹配,您不需要搜索整个字符串。

    此外,由于我不检查整数值,而是比较字符串,因此不必担心严格的===大小写。然而,==是一个好习惯。

    function startsWith($haystack,$needle) {
      substring($haystack,0,strlen($needle)) == $needle) { return true; }
       return false;
    }
    
    function endsWith($haystack,$needle) {
      if(substring($haystack,-strlen($needle)) == $needle) { return true; }
       return false;
    }
    

    或者更优化。

    function startsWith($haystack,$needle) {
      return substring($haystack,0,strlen($needle)) == $needle);
    }
    
    function endsWith($haystack,$needle) {
      return substring($haystack,-strlen($needle)) == $needle);
    }