Table Of Contents
Problem
You need to create functions that accept any data type, but using no type declaration makes code unclear and mixed
provides better documentation.
Solution
// Basic mixed type usage
function processAnyValue(mixed $value): string {
return "Received: " . gettype($value) . " with value: " . var_export($value, true);
}
echo processAnyValue(42); // Received: integer with value: 42
echo processAnyValue("hello"); // Received: string with value: 'hello'
echo processAnyValue([1, 2, 3]); // Received: array with value: array(...)
echo processAnyValue(true); // Received: boolean with value: true
// JSON data handling
function parseJsonValue(mixed $value): mixed {
if (is_string($value)) {
return json_decode($value, true);
}
if (is_array($value) || is_object($value)) {
return $value; // Already parsed
}
return $value; // Primitive value
}
$jsonString = '{"name": "John", "age": 30}';
$arrayData = ["name" => "Jane", "age" => 25];
$objectData = (object)["name" => "Bob", "age" => 35];
$result1 = parseJsonValue($jsonString); // Parsed array
$result2 = parseJsonValue($arrayData); // Original array
$result3 = parseJsonValue($objectData); // Original object
// Database value formatting
function formatDbValue(mixed $value): string {
return match (true) {
$value === null => 'NULL',
is_bool($value) => $value ? 'TRUE' : 'FALSE',
is_int($value) || is_float($value) => (string)$value,
is_string($value) => "'" . addslashes($value) . "'",
is_array($value) => "'" . addslashes(json_encode($value)) . "'",
is_object($value) => "'" . addslashes(serialize($value)) . "'",
default => 'NULL'
};
}
echo formatDbValue(123); // 123
echo formatDbValue("O'Connor"); // 'O\'Connor'
echo formatDbValue(['a', 'b']); // '["a","b"]'
echo formatDbValue(null); // NULL
// Cache storage
class Cache {
private array $storage = [];
public function set(string $key, mixed $value, int $ttl = 3600): void {
$this->storage[$key] = [
'value' => $value,
'expires' => time() + $ttl
];
}
public function get(string $key): mixed {
if (!isset($this->storage[$key])) {
return null;
}
$item = $this->storage[$key];
if (time() > $item['expires']) {
unset($this->storage[$key]);
return null;
}
return $item['value'];
}
}
$cache = new Cache();
$cache->set('user_id', 123);
$cache->set('user_data', ['name' => 'John', 'email' => 'john@example.com']);
$cache->set('is_admin', true);
$cache->set('config', (object)['theme' => 'dark']);
// Configuration management
class Config {
private array $config = [];
public function set(string $key, mixed $value): void {
$this->config[$key] = $value;
}
public function get(string $key, mixed $default = null): mixed {
return $this->config[$key] ?? $default;
}
public function has(string $key): bool {
return array_key_exists($key, $this->config);
}
}
$config = new Config();
$config->set('app.name', 'My Application');
$config->set('app.debug', true);
$config->set('database.connections', [
'default' => ['host' => 'localhost', 'port' => 3306]
]);
// API request handling
function processApiRequest(mixed $data): array {
// Normalize input data
if (is_string($data)) {
$data = json_decode($data, true);
}
if (!is_array($data)) {
return ['error' => 'Invalid data format'];
}
return [
'success' => true,
'processed_data' => $data,
'timestamp' => time()
];
}
// Form data processing
function sanitizeFormInput(mixed $input): mixed {
if (is_string($input)) {
return htmlspecialchars(trim($input), ENT_QUOTES, 'UTF-8');
}
if (is_array($input)) {
return array_map('sanitizeFormInput', $input);
}
if (is_object($input)) {
foreach ($input as $property => $value) {
$input->$property = sanitizeFormInput($value);
}
return $input;
}
return $input; // Return as-is for other types
}
$formData = [
'name' => ' John Doe ',
'email' => 'john@example.com',
'message' => '<script>alert("xss")</script>Hello',
'preferences' => [
'theme' => ' dark ',
'notifications' => true
]
];
$sanitized = sanitizeFormInput($formData);
// Event data handling
class EventDispatcher {
private array $listeners = [];
public function on(string $event, callable $callback): void {
$this->listeners[$event][] = $callback;
}
public function emit(string $event, mixed $data = null): void {
if (!isset($this->listeners[$event])) {
return;
}
foreach ($this->listeners[$event] as $callback) {
$callback($data);
}
}
}
$dispatcher = new EventDispatcher();
$dispatcher->on('user.login', function(mixed $data) {
echo "User logged in: " . json_encode($data) . "\n";
});
$dispatcher->emit('user.login', ['user_id' => 123, 'timestamp' => time()]);
$dispatcher->emit('user.login', 'Simple string data');
// Type validation utility
function validateType(mixed $value, string $expectedType): bool {
return match ($expectedType) {
'string' => is_string($value),
'int', 'integer' => is_int($value),
'float', 'double' => is_float($value),
'bool', 'boolean' => is_bool($value),
'array' => is_array($value),
'object' => is_object($value),
'null' => is_null($value),
'numeric' => is_numeric($value),
'scalar' => is_scalar($value),
'callable' => is_callable($value),
default => false
};
}
// Logging system
class Logger {
public function log(string $level, string $message, mixed $context = null): void {
$timestamp = date('Y-m-d H:i:s');
$contextStr = '';
if ($context !== null) {
$contextStr = ' Context: ';
if (is_scalar($context)) {
$contextStr .= (string)$context;
} else {
$contextStr .= json_encode($context);
}
}
echo "[{$timestamp}] {$level}: {$message}{$contextStr}\n";
}
public function error(string $message, mixed $context = null): void {
$this->log('ERROR', $message, $context);
}
public function info(string $message, mixed $context = null): void {
$this->log('INFO', $message, $context);
}
}
$logger = new Logger();
$logger->info('Application started');
$logger->error('Database connection failed', ['host' => 'localhost', 'port' => 3306]);
$logger->info('User action', 'User clicked button');
// Data transformation pipeline
function transformData(mixed $data, array $transformers): mixed {
foreach ($transformers as $transformer) {
if (is_callable($transformer)) {
$data = $transformer($data);
}
}
return $data;
}
$data = " HELLO WORLD ";
$transformed = transformData($data, [
'trim',
'strtolower',
fn($str) => str_replace(' ', '_', $str)
]);
// Result: "hello_world"
// Session data handling
class Session {
public function set(string $key, mixed $value): void {
$_SESSION[$key] = $value;
}
public function get(string $key, mixed $default = null): mixed {
return $_SESSION[$key] ?? $default;
}
public function flash(string $key, mixed $value): void {
$_SESSION['_flash'][$key] = $value;
}
public function getFlash(string $key, mixed $default = null): mixed {
$value = $_SESSION['_flash'][$key] ?? $default;
unset($_SESSION['_flash'][$key]);
return $value;
}
}
// Performance consideration: type checking
function processValue(mixed $value): string {
// Fast type checking for performance-critical code
if (is_string($value)) {
return "String: " . $value;
}
if (is_int($value)) {
return "Integer: " . $value;
}
if (is_array($value)) {
return "Array with " . count($value) . " elements";
}
// Fallback for other types
return "Other: " . gettype($value);
}
// Best practices: when to use mixed
// ✅ Good uses:
// - Generic containers (arrays, collections)
// - Configuration systems
// - Cache implementations
// - JSON/API data handling
// - Event systems
// ❌ Avoid mixed when:
// - You know the specific types needed
// - Type safety is critical
// - Performance is crucial (type checking overhead)
// - Union types can be more specific
Explanation
The mixed
type accepts any value type and is equivalent to string|int|float|bool|array|object|callable|resource|null
. Use it when true flexibility is needed.
Always add runtime type checking with is_*()
functions or gettype()
when using mixed
. Consider union types for better type safety when possible.
Share this article
Add Comment
No comments yet. Be the first to comment!