Introducción: dos enfoques, un mismo objetivo
\n\nTodo desarrollador PHP, tarde o temprano, se enfrenta a una decisión: escribir en estilo funcional o sumergirse en el mundo de las clases y objetos. Es como elegir entre una navaja suiza y una multiherramienta: ambos resuelven problemas, pero de manera diferente. En este artículo analizaremos el enfoque funcional vs la programación orientada a objetos en PHP, veremos código real y decidiremos cuándo usar cada herramienta.
\n\nPHP es un lenguaje único. Nació como procedural, evolucionó a POO y, en sus versiones más recientes (7.4+, 8.x), ha incorporado características funcionales: funciones flecha, clausuras, tipado. Esto significa que puedes combinar ambos enfoques. Pero, ¿cómo no confundirse? Vamos a descubrirlo.
\n\nFundamentos: en qué se diferencian estos dos mundos
\n\nEnfoque funcional (Functional Programming)
\n\nAquí lo principal son las funciones. Funciones puras sin efectos secundarios que siempre devuelven un resultado predecible. Nada de estado global, nada de mutaciones en variables. Los datos fluyen en cadena, como en una línea de ensamblaje.
\n\n// Estilo funcional: simple y predecible\n$numbers = [1, 2, 3, 4, 5];\n\n$result = array_map(\n fn($n) => $n * 2,\n array_filter($numbers, fn($n) => $n % 2 === 0)\n);\n\nprint_r($result); // [4, 8]\n\n¿Notaste? No modificamos el array original, no usamos bucles. Todo es declarativo: tomar los pares, duplicarlos, entregarlos. Esto ahorra tiempo en depuración, ya que no hay efectos secundarios.
\n\nEnfoque orientado a objetos (POO)
\n\nLa POO se basa en objetos: entidades que almacenan estado y comportamiento. Las clases encapsulan datos, las herencias extienden funcionalidades y el polimorfismo permite cambiar la lógica sobre la marcha.
\n\n// Estilo POO: estructura y reutilización\nclass NumberProcessor {\n private array $numbers;\n\n public function __construct(array $numbers) {\n $this->numbers = $numbers;\n }\n\n public function getEvens(): array {\n return array_filter($this->numbers, fn($n) => $n % 2 === 0);\n }\n\n public function multiplyBy(int $factor): self {\n $this->numbers = array_map(fn($n) => $n * $factor, $this->numbers);\n return $this;\n }\n\n public function getResult(): array {\n return $this->numbers;\n }\n}\n\n$processor = new NumberProcessor([1, 2, 3, 4, 5]);\n$result = $processor->getEvens()->multiplyBy(2)->getResult();\nprint_r($result); // [4, 8]\n\nAquí creamos un objeto que almacena estado. Podemos encadenar métodos. Ventaja: si necesitas agregar una nueva operación, solo añades un método a la clase.
\n\nCuándo gana el enfoque funcional
\n\n1. Procesamiento de datos sin efectos secundarios
\n\nImagina que escribes un analizador de logs o un conversor de monedas. Los datos fluyen en una línea: leer → filtrar → transformar → guardar. Las funciones son la opción ideal. No dependen del estado externo y son fáciles de probar.
\n\n2. Colecciones y arrays
\n\nPHP ofrece potentes funciones para trabajar con arrays: array_map, array_filter, array_reduce. Combinadas con funciones flecha (PHP 7.4+), convierten el código en poesía.
$users = [\n ['name' => 'Ana', 'age' => 25],\n ['name' => 'Boris', 'age' => 17],\n ['name' => 'Vicky', 'age' => 30],\n];\n\n$adultNames = array_map(\n fn($user) => $user['name'],\n array_filter($users, fn($user) => $user['age'] >= 18)\n);\n\n// ['Ana', 'Vicky']\n\nLimpio, legible, sin clases. Para transformaciones simples, es la mejor opción.
\n\n3. Pruebas sin mocks
\n\nLas funciones no tienen estado, por lo que son fáciles de probar. No necesitas crear mocks o stubs complejos. Simplemente pasas datos y obtienes un resultado.
\n\nCuándo el enfoque orientado a objetos es indispensable
\n\n1. Lógica de negocio compleja con estado
\n\n