Question

I want to normalize (so canonicalize) a string into the normal form for names:

  1. First letter of the name is uppercase

The difficulty by this is now to follow this rule with second and third name.

My method:

    public function namilize($string)
{
    $strings = explode(' ', $string);
    foreach ($strings as $string) {
        $string = ucfirst(strtolower($string));
    }
    $string = implode(' ', $strings);

    return $string;
}

Somehow the

$string = ucfirst(strtolower($string));

fails.

What do I have to correct? Is there a better way?

Regards

EDIT:

Hi,

thank you all for all the comments and answers. I found another "modern" method:

public function namilize($string)
{
    $string = mb_convert_case($string, MB_CASE_TITLE, mb_detect_encoding($string));
}

When I now would additionally add some regex for Mc and O's than it would be complete :)

Was it helpful?

Solution

public function namilize($name) {
    $name = strtolower($name);
    $normalized = array();

    foreach (preg_split('/([^a-z])/', $name, NULL, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY) as $word) {
        if (preg_match('/^(mc)(.*)$/', $word, $matches)) {
            $word = $matches[1] . ucfirst($matches[2]);
        }

        $normalized[] = ucfirst($word);
    }

    return implode('', $normalized);
}

Note that this will work for names like John O'Brian, James McManus, etc. For other names with prefixes like McManus, simply add the prefix to the preg_match(). Obviously, this runs the possibility of false positives, but no method is going to be 100% foolproof.

OTHER TIPS

You have to pass the $string by reference, note the &:

    public function namilize($string)
{
    $strings = explode(' ', $string);
    foreach ($strings as &$string) {
        $string = ucfirst(strtolower($string));
    }
    $string = implode(' ', $strings);

    return $string;
}

Or use the function suggested by @thetaiko ucwords($string)

The $string inside the foreach will only store the last iteration (or the last name). This doesn't really matter though because the variable in the foreach is never used for output. The implode just undoes what you did with the explode so you will end up with the exact same output as the input. I changed the variable names to be more descriptive in this example:

function namilize($name_in)
{
    $a_names = explode(' ', $name_in); //explode string into array
    foreach ($a_names as $name) {
        $a_fullname[] = ucfirst(strtolower($name)); //build array of proper case names
    }    
    $string = implode(' ', $a_fullname); //convert array into string
    return $string;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top