My suggestion is to use mb_convert_case
( that will support accents ) to normalize and preg_split
to divide
Note: To use mb_
functions you must enable mbstring
In php.ini remove ;
ahead of (if it's Windows):
from ;extension=php_mbstring.dll
to extension=php_mbstring.dll
If it's Linux:
from ;extension=mbstring.so
to extension=mbstring.so
If it is PHP7.2 :
from ;extension=mbstring
to extension=mbstring
<?php
/**
* Encurta nomes do meio com suporte para unicode e acentos
*
* @param string $name Define nome para ser encurtado
* @param array|null $ignore Nomes/palavras que NÃO devem ser encurtados
* @return string $encode Define a codificação do nome (opcional)
*/
function mb_shorten_name($name, array $ignore = null, $encode = null)
{
$ignore = $ignore === null ? array( 'de', 'da', 'do', 'dos' ) : $ignore;
//Converte para case-title
if ($encode) {
$name = mb_convert_case($name, MB_CASE_TITLE, $encode);
} else {
$name = mb_convert_case($name, MB_CASE_TITLE);
}
//Divide a string
$names = preg_split('#\s+#', $name);
$j = count($names);
// caso alguém tenha um só nome
if ($j === 1) return trim($name);
//Acaso só tenha menos de 3 nomes
if ($j < 3) return implode(' ', $names);
$j--;
$rebuild = array( $names[0] );
for ($i = 1; $i < $j; $i++) {
$ex = $encode ? mb_strtolower($names[$i], $encode) : mb_strtolower($names[$i]);
if (in_array($ex, $ignore)) {
$rebuild[] = $ex;
} elseif ($encode) {
$rebuild[] = mb_substr($names[$i], 0, 1, $encode) . '.';
} else {
$rebuild[] = mb_substr($names[$i], 0, 1) . '.';
}
}
$rebuild[] = $names[$j];
return implode(' ', $rebuild);
}
var_dump(mb_shorten_name('joão marques almeida de castro filho')); # João M. A. de C. Filho
var_dump(mb_shorten_name('maria gimenez almeida alburqueque da Silva')); # Maria G. A. A. da Silva
Note that I added an additional parameter called exceptions for names that should not be shortened, such as
de
,
do
and
da
, you can customize, for example I added
von
to the exception:
mb_shorten_name('Victor von Doom Junior', array( 'von' ))
Will return:
Victor von D. Junior
Note also that the third parameter is called $encode
:
mb_shorten_name($name, [array $ignore, [$encode = null])
And you can adjust it for different encodings, or you can even try to detect the encoding with mb_detect_encoding
, an example if you are sure of the type of encoding you see:
var_dump( mb_shorten_name($texto, null, 'UTF-8') ); # se a sua string for UTF-8
var_dump( mb_shorten_name($texto, null, 'ISO-8859-1') ); # se a sua string for ISO-8859-1
Example in Rep.it: link
If the names do not have accents or this is not a problem you can simply try to use:
<?php
/**
* Encurta nomes sem acentos e com caracteres ASCII
*
* @param string $name Define nome para ser encurtado
* @param array $ignore Nomes/palavras que devem ser encurtados
*/
function shorten_name($name, array $ignore = array( 'de', 'da', 'do', 'dos' ))
{
//Converte para case-title
$name = ucwords(strtolower($name));
//Divide a string
$names = preg_split('#\s+#', $name);
$j = count($names);
// caso alguém tenha um só nome
if ($j === 1) return trim($name);
// Acaso só tenha 2 nomes
if ($j < 3) return implode(' ', $names);
$j--;
$rebuild = array( $names[0] );
for ($i = 1; $i < $j; $i++) {
$ex = strtolower($names[$i]);
if (in_array($ex, $ignore)) {
$rebuild[] = strtolower($names[$i]);
} else {
$rebuild[] = substr($names[$i], 0, 1) . '.';
}
}
$rebuild[] = $names[$j];
return implode(' ', $rebuild);
}
var_dump(shorten_name('james bond de morais junior')); # James B. de M. Junior
var_dump(shorten_name('Kate Jennifer Bethan da Silva')); # Kate J. B. da Silva
Example in Rep.it: link