ucfirst() function for multibyte character encodings
Asked Answered
T

8

81

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.

Tiddlywinks answered 25/3, 2010 at 17:33 Comment(2)
Maybe this: if-not-true-then-false.com/2010/…Imponderabilia
P.S. There is a composer package with properly implemented mbUcFirst() github.com/cofirazak/phpMissingFunctionsMechanic
D
134

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;
}
Diesel answered 25/3, 2010 at 17:43 Comment(9)
how does this compares with the other users-entered customized functions? for example, 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 alreadyFootpace
you can actually pass NULL instead of $strlen-1 and then you don't need the first line.Sangsanger
Really? That sounds a little weird. null as a third parameter to mb_substr means length minus one?Diesel
@zneak: ivanhoe is right. $strlen - 1 in this case means "up to the end of the string", which is what null does here.Cleora
This didn't work for me. As per 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."Jawbreaker
@exizt that's because you're using an old PHP version. php.net/manual/en/…Adopted
@Diesel 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_ functionsTobi
$encoding should default to null and run mb_internal_encoding() if it is null.Dulcy
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.Clemente
U
94

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.

Unreeve answered 22/8, 2012 at 3:49 Comment(5)
Almost the best answer but Koralek M. is more usefull - it is insensitive for change of encoding of your www serviceCran
@Cran This one may also be insensitive for change of encoding if you omit 'UTF-8' parameter. As for every mb_* functionsMonochromatism
Works perfectly. For all intents and purposes this is the built-in mb_ucfirst equivalent in PHP.Serilda
This does not perfectly as it changes first letters in all words to uppercase. Ucfirst is supposed to change only the first word.Doreendorelia
this will touch every word in the string, that's NOT what ucfirst() does. -1Dulcy
T
35
function mb_ucfirst($string)
{
    return mb_strtoupper(mb_substr($string, 0, 1)).mb_substr($string, 1);
}
Tempura answered 4/1, 2013 at 16:52 Comment(7)
You should not lowercase the rest of the string.Macrobiotics
It is working ok. If it's not, check if mb_* functions do work in your environment at all.Reneerenegade
This function requires PHP/5.4.8 and greater. Also, you probably need to set a good locale and ensure that mb_internal_encoding() returns a proper value.Orthogenesis
this does not allow you to specify encodingDulcy
.. and worse, it will lowercase everything else in the string, that's not what ucfirst() does...Dulcy
not lowercasing anymore - a good soul went ahead and fixed it... not sure if that's legit, though? Sort of made correct a wrong answer.Illusive
@Illusive it's better now, but still not perfect, it does not allow you to specify encoding, unlike every other mb_ function ^^Dulcy
D
14

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);
}
Dulcy answered 18/11, 2019 at 13:25 Comment(4)
ps: if you're curious, i added a comment in every other answer, explaining what i think they got wrong.Dulcy
P.S. There is a composer package with properly implemented mbUcFirst() github.com/cofirazak/phpMissingFunctionsMechanic
@Dulcy 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)Mandrill
@Mandrill 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 thoughDulcy
D
7
if (!function_exists('mb_ucfirst'))
{
    function mb_ucfirst($value)
    {
        return mb_strtoupper(mb_substr($value, 0, 1)) . mb_substr($value, 1);
    }
}
Dilator answered 12/5, 2015 at 5:49 Comment(3)
It is working ok. If it's not, check if mb_* functions do work in your environment at all.Reneerenegade
This function requires PHP/5.4.8 and greater. Also, you probably need to set a good locale and ensure that mb_internal_encoding() returns a proper value.Orthogenesis
this does not allow you to specify encoding =/Dulcy
L
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 );
}
Lasseter answered 2/4, 2012 at 12:56 Comment(1)
For more general use, $main_encoding should be either set as an optional parameter or by mb_internal_encoding(). Otherwise good.Cleora
K
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;
}
Khanate answered 12/2, 2014 at 15:15 Comment(4)
This function requires PHP/5.4.8 and greater. Also, you probably need to set a good locale and ensure that mb_internal_encoding() returns a proper value.Orthogenesis
This advice was provided earlier. This code-only answer is redundant.Samoyed
default should be mb_internal_encoding() , not UTF-8 =/Dulcy
there's no need to do mb_strlen($string, $encoding)-1 - if you want the rest of the string, no matter how big it is, just specify the length as nullDulcy
P
-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);
Plovdiv answered 21/5, 2019 at 11:14 Comment(2)
please elaborate more on your answerInjection
this will uppercase every first word after spaces, and then it will trim the result, thats NOT what ucfirst() does. -1Dulcy

© 2022 - 2024 — McMap. All rights reserved.