DEV Community

Cover image for Trabajar con variables como si fuesen objetos
oskar calvo
oskar calvo

Posted on

Trabajar con variables como si fuesen objetos

Este artículo es una opinión personal y no estoy intentando sentar cátedra de nada.

Una de las cosas que más me gusta de lenguajes como Ruby o JavaScript es que sus variable son objetos, me parece mucho más legible el código en algunos aspectos, otras veces no tanto.

Un ejemplo sería.

# Ruby Program for length method.
str = "Hello, world!"
puts str.length # prints 13 to the console
Enter fullscreen mode Exit fullscreen mode

Mientas que en PHP es

$str = 'Hello, world!';
echo strlen($str);
Enter fullscreen mode Exit fullscreen mode

Lo dicho, desde mi punto de vista es más legible la forma de Ruby o de JavasScript porque vendría a ser la variable que es el sujeto y el método sería el predicado.

PHP no soporta esta forma de escribir código y es por ello que he creado una clase que permite hacerlo, pero el propósito de la clase es únicamente para jugar, no está pensada para usarla en producción ya que puede tener problemas de rendimiento.

<?php

namespace Scalar;

use Exception;
use ReflectionFunction;

class Scalar {

  /**
   * @var mixed
   * Value that can only be scalar.
   */
  private $Scalar;

  /**
   * Constructor: Initializes the Scalar object.
   * @param mixed $Scalar
   * @throws Exception if the value is not scalar.
   */
  public function __construct($Scalar) {
    if (!is_scalar($Scalar)) {
      throw new Exception('It\'s not a scalar value');
    }
    $this->Scalar = $Scalar;
  }

  /**
   * Magic method: Dynamically calls a PHP function with the scalar value.
   * Supports named parameters if provided as an associative array.
   * @param string $method The name of the function to call.
   * @param array $arguments Additional arguments for the function.
   * @return mixed The result of the function call.
   * @throws Exception if the function does not exist.
   */
  public function __call($method, $arguments) {
    if (!function_exists($method)) {
      throw new Exception('The function called ' . $method . ' doesn\'t exist');
    }

    // Verificar si los argumentos son asociativos (named parameters)
    if (!empty($arguments) && array_keys($arguments) !== range(0, count($arguments) - 1)) {
      $refFunc = new ReflectionFunction($method);
      $params = $refFunc->getParameters();

      $mappedArgs = [];
      foreach ($params as $param) {
        $name = $param->getName();
        if (isset($arguments[$name])) {
          // Asignar el valor proporcionado
          $mappedArgs[] = $arguments[$name];
        } elseif ($name === 'data') {
          // Insertar $this->Scalar si el parámetro es 'data'
          $mappedArgs[] = $this->Scalar;
        } elseif ($param->isDefaultValueAvailable()) {
          // Usar el valor predeterminado si está disponible
          $mappedArgs[] = $param->getDefaultValue();
        } else {
          // Parámetro requerido sin valor proporcionado
          throw new Exception("Missing required parameter: $name for function $method");
        }
      }

      return $refFunc->invokeArgs($mappedArgs);
    } else {
      // Llamada con argumentos posicionales (por defecto, insertar scalar al inicio)
      array_unshift($arguments, $this->Scalar);
      return call_user_func_array($method, $arguments);
    }
  }

  /**
   * Get the scalar value.
   * @return mixed
   */
  public function getScalar() {
    return $this->Scalar;
  }
}




Enter fullscreen mode Exit fullscreen mode

Además es importante tener en cuenta que para que funciona bien es necesario usar la funcionanlidad de escribir las variables con su nombre por delante

<?PHP
$data = new CustomerData(
    name: $input['name'],
    email: $input['email'],
    age: $input['age'],
);
Enter fullscreen mode Exit fullscreen mode

Un ejemplo de uso de la clase con una función de un único parámetro y una función con varios parámetros:

<?PHP
try {
    $a = 'hola mundo';
    $a_object = new Scalar($a);

    // Llamar a la función hash con named parameters
    $result = $a_object->hash(algo: 'sha256', binary: true);
    echo $result; // Hash binario de 'hola mundo'

    // Llamar a otras funciones
    echo $a_object->strlen(); // Devuelve 10 (longitud de 'hola mundo')
} catch (Exception $e) {
    echo 'Error: ' . $e->getMessage();
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)