ecommit/scalar-values
Tiny PHP utility to validate and filter arrays of scalar values. Check whether an array contains only scalars (string/int/float/bool/null), or remove non-scalar items at the root level and return the cleaned array.
Installation:
composer require ecommit/scalar-values
Add to composer.json under require-dev if only for testing:
"require-dev": {
"ecommit/scalar-values": "^1.0"
}
First Use Case: Validate form input arrays or API payloads to ensure they contain only scalar values (strings, integers, floats, booleans, null) before processing:
use Ecommit\ScalarValues\ScalarValues;
$userInput = $_POST['data'] ?? [];
if (ScalarValues::containsOnlyScalarValues($userInput)) {
// Safe to process (e.g., store in DB or pass to a service)
$this->processScalarData($userInput);
} else {
throw new \InvalidArgumentException('Input contains non-scalar values.');
}
Where to Look First:
containsOnlyScalarValues() and filterScalarValues() in Ecommit\ScalarValues\ScalarValues.tests/ for edge cases (e.g., nested arrays, objects, resources).Input Sanitization:
Use filterScalarValues() to clean user input before storage or API calls:
$cleanedData = ScalarValues::filterScalarValues($rawInput);
$this->repository->save($cleanedData);
Validation Middleware: Create a middleware to validate scalar-only arrays in routes:
namespace App\Http\Middleware;
use Closure;
use Ecommit\ScalarValues\ScalarValues;
class ValidateScalarInput
{
public function handle($request, Closure $next)
{
$data = $request->all();
if (!ScalarValues::containsOnlyScalarValues($data)) {
abort(400, 'Non-scalar values detected in input.');
}
return $next($request);
}
}
Form Request Validation:
Extend Laravel’s FormRequest to validate scalar arrays:
use Ecommit\ScalarValues\ScalarValues;
public function rules()
{
$data = $this->all();
if (!ScalarValues::containsOnlyScalarValues($data)) {
return ['data' => 'array'];
}
return ['data.*' => 'sometimes|string|integer|boolean|null'];
}
API Response Filtering: Ensure API responses only return scalar values to clients:
$responseData = ScalarValues::filterScalarValues($model->toArray());
return response()->json($responseData);
Configuration Validation:
Validate config arrays (e.g., config/app.php) during boot:
public function boot()
{
$config = config('app');
if (!ScalarValues::containsOnlyScalarValues($config)) {
throw new \RuntimeException('Invalid config: Non-scalar values found.');
}
}
Laravel Service Providers: Bind the package to the container for dependency injection:
$this->app->singleton('scalarValues', function () {
return new \Ecommit\ScalarValues\ScalarValues();
});
Then inject via constructor:
public function __construct(private ScalarValues $scalarValues) {}
Custom Rules: Create a reusable validation rule:
use Illuminate\Contracts\Validation\Rule;
use Ecommit\ScalarValues\ScalarValues;
class ScalarArray implements Rule
{
public function passes($attribute, $value)
{
return ScalarValues::containsOnlyScalarValues($value);
}
public function message()
{
return 'The :attribute must contain only scalar values.';
}
}
Use in validation:
'data' => ['required', new ScalarArray],
Testing: Use the package in PHPUnit tests to assert scalar-only arrays:
use Ecommit\ScalarValues\ScalarValues;
public function testArrayContainsOnlyScalars()
{
$this->assertTrue(ScalarValues::containsOnlyScalarValues(['a', 1, true]));
$this->assertFalse(ScalarValues::containsOnlyScalarValues(['a', ['nested']]));
}
Nested Arrays:
containsOnlyScalarValues() only checks root-level values. Nested arrays/objects will return true even if they contain non-scalars.filterScalarValues() for deep cleaning.// Recursive check (custom implementation)
function isFullyScalar($array) {
foreach ($array as $value) {
if (is_array($value)) {
if (!isFullyScalar($value)) return false;
} elseif (!is_scalar($value)) {
return false;
}
}
return true;
}
Resource Handling:
false in checks. Ensure resources are closed before validation.Edge Cases:
null is considered scalar, but false/true are also scalars. Test boundary conditions:$array = [null, false, true, 0, '0', ''];
$this->assertTrue(ScalarValues::containsOnlyScalarValues($array));
Performance:
filterScalarValues() creates a new array. For large arrays, consider in-place filtering (though this package doesn’t support it natively).Unexpected false Results:
stdClass instances). Use var_dump or gettype() to inspect:foreach ($array as $value) {
var_dump(gettype($value));
}
Filtering Side Effects:
filterScalarValues() preserves keys but reindexes the array. Use array_values() if you need sequential keys:$filtered = array_values(ScalarValues::filterScalarValues($array));
Laravel Collections:
$array = $collection->toArray();
if (ScalarValues::containsOnlyScalarValues($array)) { ... }
Custom Scalar Types:
class ExtendedScalarValues extends \Ecommit\ScalarValues\ScalarValues
{
protected function isScalar($value): bool
{
return parent::isScalar($value) || $value instanceof \DateTime;
}
}
Deep Filtering:
public static function filterScalarValuesRecursive(array $array): array
{
return array_map(function ($value) {
return is_array($value)
? self::filterScalarValuesRecursive($value)
: (is_scalar($value) ? $value : null);
}, $array);
}
Integration with Laravel:
Collection class:use Illuminate\Support\Collection;
Collection::macro('filterScalars', function () {
return new static(ScalarValues::filterScalarValues($this->all()));
});
Usage:
$collection->filterScalars();
Configuration:
config/scalar-values.php) to customize behavior (e.g., allowed non-scalar types):return [
'allowed_non_scalars' => [
\DateTime::class,
\Illuminate\Support\Carbon::class,
],
];
Then modify the package logic to respect this config.
No Built-in Config: The package has no default config file. If extending, create one to avoid magic strings or hardcoded values.
Type Strictness:
PHP’s is_scalar() is used internally. For stricter checks (e.g., excluding null), override the method:
protected function isScalar($value): bool
{
return is_scalar($value) && $value !== null;
}
How can I help you explore Laravel packages today?