Repository: laravel/framework
File: src/Illuminate/Support/Str.php (PHP)

Code before:
     * @return string
     */
    public static function lcfirst($string)
    {
        return static::lower(static::substr($string, 0, 1)).static::substr($string, 1);
    }

    /**
     * Make a string's first character uppercase.
     *
     * @param  string  $string
     * @return string
     */
    public static function ucfirst($string)
    {
        return static::upper(static::substr($string, 0, 1)).static::substr($string, 1);
    }

    /**
     * Capitalize the first character of each word in a string.
     *
     * @param  string  $string
     * @param  string  $delimiter
     * @return string
     */
    public static function ucwords($string, $delimiter = ' ')
    {
        $words = explode($delimiter, $string);

        foreach ($words as &$word) {
            $word = static::ucfirst($word);
        }

        return implode($delimiter, $words);
    }

    /**
     * Split a string into pieces by uppercase characters.
     *
     * @param  string  $string
     * @return string[]
     */
    public static function ucsplit($string)
    {
        return preg_split('/(?=\p{Lu})/u', $string, -1, PREG_SPLIT_NO_EMPTY);
    }

    /**
     * Get the number of words a string contains.
     *
     * @param  string  $string

Review comment (suggestion):
Is there a reason why `ucwords()` defaults to `' \t\r\n\f\v'` for `$delimiter`, while `Str::ucwords()` only defaults to `' '` in that case?

Also, to make the word-splitting safe, this should be the default:
```php
    /**
     * Capitalize the first character of each word in a string.
     *
     * @param  string  $string
     * @param  string|null  $delimiter
     * @return string
     */
    public static function ucwords($string, $delimiter = null)
    {
        $words = $delimiter === null
            ? mb_split('\s+', $value)
            : explode($delimiter, $string);

        foreach ($words as &$word) {
            $word = static::ucfirst($word);
        }

        return implode($delimiter ?? ' ', $words);
    }
```

Code after:
     * @return string
     */
    public static function lcfirst($string)
    {
        return static::lower(static::substr($string, 0, 1)).static::substr($string, 1);
    }

    /**
     * Make a string's first character uppercase.
     *
     * @param  string  $string
     * @return string
     */
    public static function ucfirst($string)
    {
        return static::upper(static::substr($string, 0, 1)).static::substr($string, 1);
    }

    /**
     * Capitalize the first character of each word in a string.
     *
     * @param  string  $string
     * @param  string  $separators
     * @return string
     */
    public static function ucwords($string, $separators = " \t\r\n\f\v")
    {
        $pattern = '/(^|['.preg_quote($separators, '/').'])(\p{Ll})/u';

        return preg_replace_callback($pattern, function ($matches) {
            return $matches[1].mb_strtoupper($matches[2]);
        }, $string);
    }

    /**
     * Split a string into pieces by uppercase characters.
     *
     * @param  string  $string
     * @return string[]
     */
    public static function ucsplit($string)
    {
        return preg_split('/(?=\p{Lu})/u', $string, -1, PREG_SPLIT_NO_EMPTY);
    }

    /**
     * Get the number of words a string contains.
     *
     * @param  string  $string
     * @param  string|null  $characters
     * @return int