symfony/polyfill-ctype
Symfony Polyfill for Ctype: provides ctype_* functions when the PHP ctype extension isn’t available. Useful for consistent character-type checks across environments and PHP versions. Part of the Symfony Polyfill suite, MIT licensed.
Installation: Add the package via Composer in your Laravel project:
composer require symfony/polyfill-ctype
No additional configuration is required—it works as a drop-in replacement.
First Use Case:
Replace any ctype_* function calls in your code. For example:
// Before (may fail if ctype extension is missing)
if (ctype_alnum($input)) {
// Process alphanumeric input
}
// After (works universally)
if (\ctype_alnum($input)) { // Note: Use fully qualified namespace
// Process alphanumeric input
}
Where to Look First:
FormRequest validation rules or custom validation logic:
public function rules()
{
return [
'username' => 'required|string|max:255|ctype_alnum',
];
}
public function handle($request, Closure $next)
{
if (\ctype_alpha($request->input('param'))) {
// Proceed
}
return $next($request);
}
preg_match) with ctype_* for readability:
// Replace:
if (preg_match('/^[a-zA-Z0-9]+$/', $input)) { ... }
// With:
if (\ctype_alnum($input)) { ... }
Validation Layer Integration:
ctype_* in custom validation rules:
use Illuminate\Validation\Rule;
public function rules()
{
return [
'slug' => [
'required',
'string',
Rule::custom(function ($attribute, $value) {
return \ctype_alnum($value);
}),
],
];
}
FormRequest or create a reusable rule:
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule as ValidationRule;
class Alphanumeric implements ValidationRule
{
public function passes($attribute, $value)
{
return \ctype_alnum($value);
}
public function message()
{
return 'The :attribute must be alphanumeric.';
}
}
Usage:
'field' => ['required', new \App\Rules\Alphanumeric],
Middleware for Input Sanitization:
public function handle($request, Closure $next)
{
$input = $request->input('api_key');
if (!\ctype_alnum(str_replace('-', '', $input))) {
abort(400, 'Invalid API key format.');
}
return $next($request);
}
Slug Generation:
ctype_* checks:
public function generateSlug($title)
{
$slug = Str::slug($title);
if (\ctype_alnum($slug)) {
return $slug;
}
return preg_replace('/[^a-zA-Z0-9]+/', '-', $slug);
}
API Input Validation:
App\Exceptions\Handler or middleware:
public function validateApiInput($request)
{
$data = json_decode($request->getContent(), true);
foreach ($data as $key => $value) {
if (\ctype_digit($value) && strlen($value) > 10) {
throw new \Exception("Invalid $key format.");
}
}
}
Database Constraints:
ctype_* to validate model attributes before saving:
public function save(array $options = [])
{
if (!\ctype_alnum($this->attributes['username'])) {
throw new \InvalidArgumentException('Username must be alphanumeric.');
}
return parent::save($options);
}
Shared Hosting Compatibility:
ctype extension is disabled.composer.json and redeploy. No code changes needed.composer require symfony/polyfill-ctype
git add composer.json composer.lock
git commit -m "Add ctype polyfill for shared hosting compatibility"
git push
PHP 8.1+ Migration:
E_DEPRECATED warnings for ctype_* in PHP 8.1+.composer require symfony/polyfill-ctype
# Optionally suppress deprecation warnings in bootstrap/app.php:
error_reporting(E_ALL & ~E_DEPRECATED);
CI/CD Pipeline:
ctype extension.composer.json and ensure it’s included in all environments.# .github/workflows/tests.yml
jobs:
test:
steps:
- uses: actions/checkout@v4
- run: composer install
- run: composer require symfony/polyfill-ctype --dev --no-update
- run: composer update
- run: php artisan test
Performance Optimization:
ctype_* where possible and fall back to polyfill.if (function_exists('ctype_alnum')) {
// Use native function (faster)
$isValid = ctype_alnum($input);
} else {
// Fall back to polyfill
$isValid = \ctype_alnum($input);
}
Laravel Validation Rules:
ctype_* checks:
'username' => 'required|string|max:255|ctype_alnum',
Testing:
ctype_* functions in PHPUnit tests to avoid environment dependencies:
use Symfony\Component\Polyfill\Ctype\Ctype;
beforeEach(function () {
$this->mockCtype = $this->mock(Ctype::class);
$this->mockCtype->shouldReceive('alnum')->andReturnTrue();
});
Unicode Handling:
mbstring functions for Unicode support:
if (\mb_ctype_alnum($input, 'UTF-8')) {
// Handle Unicode alphanumeric input
}
Legacy Code:
ctype_* for consistency:
// Before:
if (preg_match('/^[a-zA-Z]+$/', $input)) { ... }
// After:
if (\ctype_alpha($input)) { ... }
Documentation:
README or CONTRIBUTING.md that ctype_* functions are polyfilled for cross-environment compatibility.Namespace Collisions:
use function ctype_alnum; or use function \ctype_alnum;, the polyfill may not be loaded due to namespace resolution.\ctype_alnum($input); // Correct
ctype_alnum($input); // May fail if native function exists
PHP 8.1+ Deprecation Warnings:
error_reporting is not configured.bootstrap/app.php:
error_reporting(E_ALL & ~E_DEPRECATED);
ctype_* with Str::isAlphanumeric() or preg_match in critical paths.Unicode Limitations:
ctype_* functions only support ASCII. For Unicode (e.g., café), use mb_ctype_* or Str::isAlphanumeric().if (\mb_ctype_alnum($input, 'UTF-8')) { ... }
// Or:
if (Str::isAlphanumeric($input)) { ... }
Performance Overhead:
How can I help you explore Laravel packages today?