78

I've asked about strtolower function. But when using foreign characters it doesn't convert them into uppercase, so I must use:

 mb_strtolower($a,"utf8");

But what can I do, if I want to use ucfirst() function? I haven't found any similar function, where I can set encoding type.

Community
  • 1
  • 1
Simon
  • 22,637
  • 36
  • 92
  • 121
  • Maybe this: http://www.if-not-true-then-false.com/2010/php-mb_ucfirst-make-a-strings-first-character-uppercase-multibyte-function/ – user956584 May 03 '12 at 20:48
  • P.S. There is a composer package with properly implemented mbUcFirst() https://github.com/cofirazak/phpMissingFunctions – cofirazak Dec 09 '19 at 09:05

8 Answers8

130

There is no mb_ucfirst function, as you've already noticed. You can fake a mb_ucfirst with two mb_substr:

function mb_ucfirst($string, $encoding)
{
    $firstChar = mb_substr($string, 0, 1, $encoding);
    $then = mb_substr($string, 1, null, $encoding);
    return mb_strtoupper($firstChar, $encoding) . $then;
}
BenMorel
  • 34,448
  • 50
  • 182
  • 322
zneak
  • 134,922
  • 42
  • 253
  • 328
  • 1
    how does this compares with the other users-entered customized functions? for example, http://php.net/manual/en/function.ucfirst.php#108856 **PS** I know I can TIAS but since lots of people have this problem someone may have the answer already – Felipe Sep 26 '12 at 00:07
  • 7
    you can actually pass NULL instead of $strlen-1 and then you don't need the first line. – ivanhoe Oct 19 '13 at 02:18
  • Really? That sounds a little weird. `null` as a third parameter to `mb_substr` means length minus one? – zneak Oct 19 '13 at 15:54
  • 1
    @zneak: ivanhoe is right. $strlen - 1 in this case means "up to the end of the string", which is what null does here. – Pavel V. Dec 19 '13 at 21:53
  • 3
    This didn't work for me. As per http://www.php.net/manual/de/function.mb-substr.php#77515: "Passing null as length will not make mb_substr use it's default, instead it will interpret it as 0." – Stas Bichenko Feb 17 '14 at 14:52
  • 4
    @exizt that's because you're using an old PHP version. http://php.net/manual/en/function.mb-substr.php#refsect1-function.mb-substr-changelog – jurchiks Aug 24 '15 at 15:12
  • 1
    @zneak You could even make the `$encoding` parameter optional and read it from `mb_internal_encoding()` when it is not set so the function behavior would be consistent with other mb_ functions – Kyborek Aug 07 '18 at 09:55
  • $encoding should default to null and run mb_internal_encoding() if it is null. – hanshenrik Nov 18 '19 at 12:49
  • You can save an mbstring call by passing `null` instead of `$strlen - 1` in `mb_substr()`; this way, you don't need the length. **edit** oops, just saw that others mentioned this before I did. Actually, as I can see on your profile page that you're no longer contributing to StackOverflow, I took the liberty to update your answer to reflect this. – BenMorel Nov 12 '20 at 16:14
93

This is more concise solution, although it is rather similar to ucwords function:

$final_string = mb_convert_case($your_string, MB_CASE_TITLE, 'UTF-8');

If you need to capitalize string consist of one word, it is the best solution.

Melebius
  • 6,183
  • 4
  • 39
  • 52
Alex Belyaev
  • 1,417
  • 1
  • 11
  • 15
  • 2
    Almost the best answer but **Koralek M. is more usefull** - it is **insensitive for change of encoding** of your www service – fider Jul 11 '13 at 09:41
  • 1
    @fider This one may also be insensitive for change of encoding if you omit 'UTF-8' parameter. As for every mb_* functions – Erdal G. Sep 29 '14 at 16:30
  • 2
    Works perfectly. For all intents and purposes this is the built-in `mb_ucfirst` equivalent in PHP. – Mahn Sep 16 '15 at 14:16
  • 25
    This does not perfectly as it changes first letters in all words to uppercase. Ucfirst is supposed to change only the first word. – Mike Doe Feb 26 '16 at 11:27
  • 8
    this will touch every word in the string, that's NOT what ucfirst() does. -1 – hanshenrik Nov 18 '19 at 12:53
34
function mb_ucfirst($string)
{
    return mb_strtoupper(mb_substr($string, 0, 1)).mb_substr($string, 1);
}
GKFX
  • 1,386
  • 1
  • 11
  • 30
Koralek M.
  • 3,231
  • 4
  • 26
  • 32
13

as of 2019-11-18, it seems nobody on stackoverflow got this right, here's how mb_ucfirst() should be implemented in userland:

For PHP>=8.0.0:

function mb_ucfirst(string $str, ?string $encoding = null): string
{
    return mb_strtoupper(mb_substr($str, 0, 1, $encoding), $encoding) . mb_substr($str, 1, null, $encoding);
}

For PHP >= 7.0.0:

function mb_ucfirst(string $str, string $encoding = null): string
{
    if ($encoding === null) {
        $encoding = mb_internal_encoding();
    }
    return mb_strtoupper(mb_substr($str, 0, 1, $encoding), $encoding) . mb_substr($str, 1, null, $encoding);
}

For PHP>=5.1.0:

function mb_ucfirst($str, $encoding = null)
{
    if (!is_string($str)) {
        throw new InvalidArgumentException("Argument 1 must be string, " . gettype($str) . " given");
    }
    if ($encoding === null) {
        $encoding = mb_internal_encoding();
    } elseif (!is_string($encoding)) {
        throw new InvalidArgumentException("Argument 2 must be string|null, " . gettype($encoding) . " given");
    }
    return mb_strtoupper(mb_substr($str, 0, 1, $encoding), $encoding) . mb_substr($str, 1, null, $encoding);
}
hanshenrik
  • 19,904
  • 4
  • 43
  • 89
  • 3
    ps: if you're curious, i added a comment in every other answer, explaining what i think they got wrong. – hanshenrik Nov 19 '19 at 06:11
  • P.S. There is a composer package with properly implemented mbUcFirst() https://github.com/cofirazak/phpMissingFunctions – cofirazak Dec 09 '19 at 09:03
  • @hanshenrik should `mb_ucfirst(string $str, ?string $encoding = null): string` declaration be better? It explicitly states that $encoding can be null, which aligns with the default value (and with existing PHP functions documentation) – Pere Jun 01 '23 at 12:29
  • 1
    @Pere yeah that'd be better. Don't think it makes a difference though. Btw prior to PHP8.0.0, calling mb_internal_encoding was actually required, as the encoding argument of mb_substr functions wasn't nullable, but was omittable. Luckily that's fixed in >=8.0.0 though – hanshenrik Jun 01 '23 at 13:29
7
if (!function_exists('mb_ucfirst'))
{
    function mb_ucfirst($value)
    {
        return mb_strtoupper(mb_substr($value, 0, 1)) . mb_substr($value, 1);
    }
}
goyote
  • 573
  • 5
  • 13
2

I´m using cp1250 on webpage, and for Ú mb_ucfirst doesn´t work, so little upgrade:

  function mb_ucfirst($string)
{
    $main_encoding = "cp1250"; 
    $inner_encoding = "utf-8";
    $string = iconv($main_encoding, $inner_encoding , $string );
    $strlen = mb_strlen($string);
    $firstChar = mb_substr($string, 0, 1, $inner_encoding);
    $then = mb_substr($string, 1, $strlen - 1, $inner_encoding);
    return $string = iconv($inner_encoding, $main_encoding , mb_strtoupper($firstChar, $inner_encoding) . $then );
}
Jaroslav Štreit
  • 415
  • 1
  • 5
  • 16
  • 2
    For more general use, $main_encoding should be either set as an optional parameter or by mb_internal_encoding(). Otherwise good. – Pavel V. Dec 19 '13 at 22:00
0
/*This worked correctly for me*/
function mb_ucfirst($string, $encoding='UTF-8')
{
    $firstChar = mb_substr($string, 0, 1, $encoding);
    $then = mb_substr($string, 1, mb_strlen($string, $encoding)-1, $encoding);
    return mb_strtoupper($firstChar, $encoding) . $then;
}
-1
$string = trim(preg_replace('/\s+/', ' ', $string));
$string_ar = explode(' ', mb_strtolower($string,'utf-8'));

foreach($string_ar as $key => $value {
  $string_str .= mb_convert_case(mb_substr(trim($value), 0, 1), MB_CASE_TITLE, 'utf-8')
    . mb_substr(trim($value),1)
    . ' ';
}

$string = trim($string_str);
Stphane
  • 3,368
  • 5
  • 32
  • 47
Paris Z
  • 19
  • 1