Заглавные буквы с использованием PHP

У меня проблемы с использованием заглавных букв в именах с использованием PHP. Есть имена, в которых две заглавные буквы (например, МакКолл). При сохранении имени пользователя, который регистрируется на нашем веб-сайте, мы запускаем следующий код:

$name = ucwords(strtolower(trim($_SESSION['last_name']))) ;

Что это делает, так это меняет «mccall» на «Mccall». Что нам нужно, так это способ проверить, начинаются ли первые 2 буквы с «Mc», и если да, то третья буква также будет заглавной, а имя изменится на «McCall».

Любая помощь приветствуется.


person three3    schedule 04.03.2012    source источник
comment
Как насчет того, чтобы позволить пользователям указывать свое собственное имя без изменений? Моя фамилия О'Хара. Фамилия некоторых людей О'Хара. Вы не сможете отличить. Как насчет Mac вместо имен Mc? Фамилии, содержащие дефис?   -  person Ry-♦    schedule 04.03.2012
comment
Некоторое время назад я столкнулся с этой же проблемой и решил просто разрешить пользователям указывать свой собственный регистр для имен, как по причинам, указанным @minitech, так и по тому факту, что, если пользователь хочет, они могут иметь имя, состоящее из заглавных букв. .   -  person Bojangles    schedule 04.03.2012
comment
Поверьте, хотелось бы, чтобы люди правильно вводили свое имя, но они этого не делают. Меня не беспокоит любое другое имя, кроме «Мак».   -  person three3    schedule 04.03.2012
comment
@three3, кто определяет правильное представление имени, кроме человека, которому оно принадлежит?   -  person imm    schedule 04.03.2012
comment
@three3: это кажется несколько высокомерным подходом к вашим пользователям.   -  person Oliver Charlesworth    schedule 04.03.2012
comment
Если вы хотите просто поймать ленивого машинистку, я бы проверил, все ли имена написаны строчными или прописными буквами, а затем выполнил ваше преобразование. Если кто-то пишет mccall или MCCALL, то они заслуживают любых ошибок, которые создает ваше исправление. (Нет ничего плохого в том, чтобы убедиться, что ваш сайт не выглядит так, будто им пользуются неграмотные дети.)   -  person Matthew    schedule 04.03.2012
comment
Я согласен с minitech, Oli Charlesworth и JamWaffles, поскольку большинство людей пишут свои имена так, как им хочется. Однако, если вы настроены на это, вы можете настроить массив с различными вариантами, найти совпадающие альфа-шаблоны и предложить пользователю варианты на выбор (включая тот, который он ввел).   -  person cjtech    schedule 04.03.2012


Ответы (3)


Вот решение, которое просто поймает Мака, если это действительно все, что вас интересует:

function capitalizeLastName($name) {
    $result = ucwords(strtolower(trim($_SESSION['last_name'])));

    if(substr($result, 0, 2) === 'Mc') {
        $result[2] = strtoupper($result[2]); // Yes, this works in PHP!
    }

    return $result;
}
person Ry-♦    schedule 04.03.2012
comment
анонимному редактору: нет, не будет, как показано в первый пример документации для ucwords. - person Ry-♦; 21.05.2014

Просто к вашему сведению, у меня есть ДЕЙСТВИТЕЛЬНО хорошая функция для заглавных букв гораздо большего, чем просто имена. Он также делает заголовки, фразы и т. д.

Он принимает строковый параметр и логическое значение. Логическое значение TRUE, если вы пишете имя с большой буквы, и FALSE или ничего, если это заголовок, фраза и т. д.

Использование так же просто, как:

capitalize('mccall', TRUE); // result 'McCall'
capitalize('merry christmas and happy holidays!'); // result 'Merry Christmas and Happy Holidays!'
capitalize('jd mckinstry', TRUE); // result 'JD McKinstry'

Функция!

function capitalize($str, $is_name=FALSE) {
    $str = trim(stripcslashes($str));

    // exceptions to standard case conversion
    if ($is_name) {
        $all_uppercase = '';//'Aj|Jd';
        $all_lowercase = 'De La|De Las|Der|Van De|Van Der|Vit De|Von|Or|And|Van ';
    }
    else {  // addresses, essay titles ... and anything else
        $all_uppercase = 'Po|Rr|Se|Sw|Ne|Nw';
        $all_lowercase = 'A|And|As|By|In|Of|Or|To';
    }

    $prefixes = 'Mc';
    $suffixes = "'S";

    // captialize all first letters
    $str = preg_replace('/\\b(\\w)/e', 'strtoupper("$1")', strtolower(trim($str)));

    if ($all_uppercase) {   // capitalize acronymns and initialisms e.g. PHP
        $str = preg_replace("/\\b($all_uppercase)\\b/e", 'strtoupper("$1")', $str);
    }

    if ($is_name) {
        if (strpos($str, " ") !== FALSE) {
            $ara = explode(" ", $str);
            foreach ($ara as $k => $v) {
                if ($k != count($ara)-1 && !preg_match("/[aeiouyAEIOUY]/", $v)) $ara[$k] = strtoupper($v);
            }
            $str = implode(" ", $ara);
        }
        elseif (!preg_match("/[aeiouy]/", $str)) {
            $str = strtoupper($str);
        }
    }

    if ($all_lowercase) {   // decapitalize short words e.g. and
        if ($is_name) { // all occurences will be changed to lowercase
            $str = preg_replace("/\\b($all_lowercase)\\b/e", 'strtolower("$1")', $str);
        }
        else {  // first and last word will not be changed to lower case (i.e. titles)
            $str = preg_replace("/(?<=\\W)($all_lowercase)(?=\\W)/e", 'strtolower("$1")', $str);
        }
    }

    if ($prefixes) {    // capitalize letter after certain name prefixes e.g 'Mc'
        $str = preg_replace("/\\b($prefixes)(\\w)/e", '"$1".strtoupper("$2")', $str);
    }

    if ($suffixes) {    // decapitalize certain word suffixes e.g. 's
        $str = preg_replace("/(\\w)($suffixes)\\b/e", '"$1".strtolower("$2")', $str);
    }

    //  Mac Exceptions
    if (strpos($str, "Macd") === FALSE || strpos($str, "Macv") === FALSE) {
        $str = preg_replace("/Macd/", 'MacD', $str);
        $str = preg_replace("/Macv/", 'MacV', $str);
    }

    return trim(stripcslashes($str));
}

Как некоторые из вас могли заметить, изначально это было взято с сайта PHP, но с тех пор я развивал его и превратили в гораздо более полезный и «интеллектуальный» метод!

person SpYk3HH    schedule 28.06.2013
comment
Preg_replace устарел! Устарело: preg_replace(): модификатор /e устарел, используйте вместо него preg_replace_callback! Обновите свой код. - person Michelangelo; 23.04.2015

Я нашел этот ответ, когда искал функцию, найденную в руководстве по PHP, на что ответил SpYk3HH.

Как правильно заметил Микеланджело, preg_replace устарел. Чтобы сэкономить время другим, здесь обновлена ​​функция.

Плюс некоторые дополнения для поддержки голландских имен:

<?php

function capitalize($str, $is_name = FALSE) {

  $mylist = "S|‘s|‘t|A|Aan|Aan ‘t|Aan De|Aan Den|Aan Der|Aan Het|Aan T|Af|Al|Am|"
      . "Am De|Auf|Auf Dem|Auf Den|Auf Der|Auf Ter|Aus|Aus ‘m|Aus Dem|Aus Den|"
      . "Aus Der|Aus M|Ben|Bij|Bij ‘t|Bij De|Bij Den|Bij Het|Bij T|Bin|Boven D|"
      . "Boven D’|D|D’|Da|Dal|Dal’|Dalla|Das|De|De Die|De Die Le|De L|De L’|"
      . "De La|De Las|De Le|De Van Der|Deca|Degli|Dei|Del|Della|Den|Der|Des|"
      . "Di|Die Le|Do|Don|Dos|Du|El|Het|I|Im|In|In ‘t|In De|In Den|In Der|"
      . "In Het|In T|L|L’|La|Las|Le|Les|Lo|Los|Of|Onder|Onder ‘t|Onder De|"
      . "Onder Den|Onder Het|Onder T|Op|Op ‘t|Op De|Op Den|Op Der|Op Gen|Op Het|"
      . "Op T|Op Ten|Over|Over ‘t|Over De|Over Den|Over Het|Over T|S’|T|Te|Ten|"
      . "Ter|Tho|Thoe|Thor|To|Toe|Tot|Uijt|Uijt ‘t|Uijt De|Uijt Den|Uijt Te De|"
      . "Uijt Ten|Uit|Uit ‘t|Uit De|Uit Den|Uit Het|Uit T|Uit Te De|Uit Ten|"
      . "Unter|Van|Van ‘t|Van De|Van De L|Van De L’|Van Den|Van Der|Van Gen|"
      . "Van Het|Van La|Van T|Van Ter|Van Van De|Ver|Vom|Von|Von ‘t|Von Dem|"
      . "Von Den|Von Der|Von T|Voor|Voor ‘t|Voor De|Voor Den|Voor In ‘t|"
      . "Voor In T|Vor|Vor Der|Zu|Zum|Zur|Vit De|Or|And|Van|En";



  $str = trim($str);
  $str = stripcslashes($str);

  // exceptions to standard case conversion
  if ($is_name) {
    $all_uppercase = ''; //'Aj|Jd';
    $all_lowercase = $mylist;
  }
  else {  // addresses, essay titles ... and anything else
    $all_uppercase = 'Po|Rr|Se|Sw|Ne|Nw';
    $all_lowercase = 'A|And|As|By|In|Of|Or|To';
  }

  $prefixes = 'Mc';
  $suffixes = "'S";

  // captialize all first letters
  $str = preg_replace_callback('/\\b(\\w)/', function($m) {
    return strtoupper($m[1]);
  }, strtolower(trim($str)));

  if ($all_uppercase) {   // capitalize acronymns and initialisms e.g. PHP
    $str = preg_replace("/\\b($all_uppercase)\\b/", function($m) {
      return strtoupper($m[1]);
    }, $str);
  }

  if ($is_name) {
    if (strpos($str, " ") !== FALSE) {
      $ara = explode(" ", $str);
      foreach ($ara as $k => $v) {
        if ($k != count($ara) - 1 && !preg_match("/[aeiouyAEIOUY]/", $v))
          $ara[$k] = strtoupper($v);
      }
      $str = implode(" ", $ara);
    }
    elseif (!preg_match("/[aeiouy]/", $str)) {
      $str = strtoupper($str);
    }
  }

  if ($all_lowercase) {   // decapitalize short words e.g. and
    if ($is_name) { // all occurences will be changed to lowercase
      $str = preg_replace_callback("/\\b($all_lowercase)\\b/", function($m) {
        return strtolower($m[1]);
      }, $str);
    }
    else {  // first and last word will not be changed to lower case (i.e. titles)
      $str = preg_replace_callback("/(?<=\\W)($all_lowercase)(?=\\W)/", function($m) {
        return strtolower($m[1]);
      }, $str);
    }
  }

  if ($prefixes) {    // capitalize letter after certain name prefixes e.g 'Mc'
    $str = preg_replace_callback("/\\b($prefixes)(\\w)/", function($m) {
      return $m[1] . strtoupper($m[2]);
    }
        , $str);
  }

  if ($suffixes) {    // decapitalize certain word suffixes e.g. 's
    $str = preg_replace_callback("/(\\w)($suffixes)\\b/", function($m) {
      return $m[1] . strtoupper($m[2]);
    }, $str);
  }

  //  Mac Exceptions
  if (strpos($str, "Macd") === FALSE || strpos($str, "Macv") === FALSE) {
    //$str = preg_replace_callback("/Macd/", 'MacD', $str);
    //$str = preg_replace_callback("/Macv/", 'MacV', $str);
  }

  return trim(stripcslashes($str));
}

//Array containing names to test
$testnames = [
  'van der vaart',
  'van vollenhoven',
  "van 't zandt",
  'van het zand',
  'el hamdoie',
  'van der Rooi-van Velzen',
  'Zuidewijn - van rooien',
  'teggelen onder t boven',
  "guido op 't drooge",
  "friso van drooge",
  'Zuidewijn - van rooien',
  'teggelen onder t boven',
  'ZUID-HOLLAND',
  "'s hertogen-bosch",
  "De Rooi Van Zuidewijn",
  "van onder",
  "Van Der Wijk-Zeewuster",
  "de Vries-van der Leest",
  "Den Oudsten - van 't Veldt",
  "Hare Koninklijke Hoogheid Alexia Juliana Marcela Laurentien Prinses der Nederlanden, Prinses van Oranje-Nassau",
  "Hare Koninklijke Hoogheid Máxima, Prinses der Nederlanden, Prinses van Oranje-Nassau, Mevrouw van Amsberg",
  "van Lippe-Biesterfeld van Vollenhoven",
];

foreach ($testnames as $name) {

  //First convert name to uppercase to get rid of the correct caps
  $name = strtoupper($name);
  //Output the capitalized name
  echo $name;
  echo " = ";
  //See output of function
  echo capitalize($name, TRUE);
  //Set br tag to get the next test name on next line
  echo "<br />";
}
person Rick B    schedule 18.07.2017
comment
van der Vaart следует начинать с заглавной V, если не указано имя. А для Бельгии действуют другие правила. - person Ivo P; 18.07.2017
comment
Правильная функция выше применима только к голландским именам, я использую эту функцию для преобразования фамилии. Если вы используете его без имени или инициалов, просто используйте ucfirst() для фамилии, и это будет правильно. - person Rick B; 18.07.2017
comment
Но помимо этого до сих пор хорошо используемая функция для голландских имен - person Ivo P; 18.07.2017