En nuestro post “Prueba tus WordPress Plugins con PHPUnit en Local” configuramos PHPUnit junto con Local para después hacer pruebas a nuestros plugins. Es una buena forma para mantener nuestro código a prueba de errores, entre otros beneficios.
(más…)Etiqueta: php
Domina el uso de tus condiciones en PHP
Conocemos las condiciones en PHP, pero ¿qué tan eficientes son las que tu escribes? Las condiciones pueden afectar la legibilidad de tu código e incluso afectar el rendimiento de tu aplicación.
Los problemas en las condiciones
He visto a desarrolladores nuevos en grupos de Facebook publicar su código, ¿y saben qué es lo que he notado? Problemas en sus condiciones:
- No son para nada legibles ni eficientes, por lo tanto, son complejas.
- Ejecutan condiciones de más, provocando el famoso callback hell.
- No utilizan las condiciones Yoda (Esto puede ser opcional en cada desarrollador, pero yo lo recomiendo como buena práctica).
Yo sufrí lo mismo; y es que cuando estás empezando a desarrollar en PHP, como que te cuesta encontrar una guía de buenas prácticas al momento de estar desarrollando.
Yo encontré la guía PHP: The Right Way muy tarde, se los recomiendo.
Nota: El código que verás en todo el post estará en inglés, ¿por qué? La respuesta te la cuento en este post sobre cómo debes nombrar tus variables apropiadamente.
Tu código debe ser legible, no lo hagas más complejo
Hay una verdad en los programadores:
Los programadores pasamos la mayor parte de nuestro tiempo leyendo código que escribiéndolo.
Por lo tanto, todo el código que nosotros escribamos, deberá ser legible para que tanto nosotros como otros programadores lo lean rápido y por ende, el código sea fácil de entender.
¿No queremos gastar nuestro tiempo tratando de adivinar lo que hace el código o si?
Lo siguiente pasa muy seguido en los desarrolladores nuevos:
<?php $animals = array( 'dog', 'cat', 'elephant', ); if( is_array( $animals ) ) { if( ! empty( $animals ) ) { do_something(); } }
¿Si notas cómo el código de arriba se hace un poco difícil de leer? Entre más tedioso sea de leer, más complejo se volverá tu código.
El código anterior es un ejemplo de condiciones anidadas. Ahora, ¿Qué ocurre cuando empiezas a anidar condición tras condición, función tras función?
Ocurre el famoso callback hell; la siguiente imagen no contiene código PHP, pero es un ejemplo muy claro de un callback hell, condiciones tras condiciones (abre la imagen en una pestaña para verla mejor, si es que te atreves):
¿Pudiste descifrar lo que hace el código? ¡Yo ni me tomé el tiempo de leerlo! Tan sólo mira esa complejidad. Eso es lo que tratamos de evitar.
La solución de nuestro código anterior sería usar los operadores lógicos, en este caso, el operador AND:
<?php $animals = array( 'dog', 'cat', 'elephant', ); if( is_array( $animals ) && ! empty( $animals ) ) { do_something(); }
¿Notas la diferencia? Es más legible y menos complejo. Los operadores lógicos están aquí para ayudarnos, así que pon atención a tus clases de Matemáticas Discretas (bueno, al menos yo lo vi en esa materia).
Usa cláusulas de guardia
Éste método funciona como un guardia que protege tu código, para poder llegar a la siguiente sección del código debes pasar ese guardia, y así sucesivamente.
Gráficamente trabaja así:
¿Pero realmente de qué sirve? Nos aporta mayor legibilidad a nuestro código, nos ayuda a no ejecutar código de más y evita el callback hell.
El siguiente ejemplo no tiene cláusulas de guardia:
<?php function is_user_registered( $username ) { $usernames_list = array( 'roelmagdaleno', 'rokumetal', 'elbuenprogramador117', ); $user_data = array(); if( in_array( $username, $usernames_list ) ) { $user_data = get_user_data( $username ); } return $user_data; }
La función anterior nos dice que si el usuario está registrado, nos retorne los datos del usuario que está tratando de iniciar sesión, en caso contrario, mandemos un array vacío.
Ahora, mira la misma función pero usando las cláusulas de guardia:
<?php function is_user_registered( $username ) { $usernames_list = array( 'roelmagdaleno', 'rokumetal', 'elbuenprogramador117', ); $user_data = array(); if( ! in_array( $username, $usernames_list ) ) { return $user_data; } return get_user_data( $username ); }
¿Ves como hemos negado la función
in_array()
? Le estamos diciendo que si el usuario no existe, retorna un array vacío, en cambio, si existe, continúa con el código y obtiene los datos del usuario.¡Así es como funcionan las cláusulas de guardia! Tienes que pasar cada guardia para proseguir ejecutando el código.
Otro ejemplo, pero ahora con condiciones anidadas:
<?php function is_current_user_admin( $username ) { $usernames_list = array( 'roelmagdaleno', 'rokumetal', 'elbuenprogramador117', ); if( in_array( $username, $usernames_list ) ) { $user_data = get_user_data( $username ); if( 'administrator' === $user_data['role'] ) { return true; } } return false; }
La función anterior valida si el usuario actual que está tratando de iniciar sesión es un administrador o no. Pero, ¿si sientes que pierdes un poco de tiempo tratando de leer el código?
Bien, entonces, la función anterior sería de la siguiente forma usando cláusulas de guardia:
<?php function is_current_user_admin( $username ) { $usernames_list = array( 'roelmagdaleno', 'rokumetal', 'elbuenprogramador117', ); if( ! in_array( $username, $usernames_list ) ) { return 'The user does not exists.'; } $user_data = get_user_data( $username ); if( 'administrator' !== $user_data['role'] ) { return false; } return true; }
¡Estupendo! Eliminamos la condición anidada y ahora es más fácil de leer el código, y un extra fue que evitamos un posible callback hell.
¿Tienes funciones que contengan condiciones anidadas? Trata de convertirlas usando cláusulas de guardia y pega tus resultados en los comentarios.
Evita usar “else” en tus condiciones
¿Enserio, no usar el
else
? Sí, hablo enserio.¿No te ha pasado que cuando usas la palabra reservada
else
, se te dificulta leer más el código? Exacto.Esta declaración lo que hace es agregarle más complejidad a nuestro código y por ende, más difícil de leer. Por ejemplo, sé que puedes leer el siguiente código, pero ¿cuánto te tardas en entender lo que realmente hace?:
<?php $username = $_POST['username']; $password = $_POST['password']; if( empty( $username ) || empty( $password ) ) { return 'user-login.php'; } elseif( ! empty( $username ) && ! empty( $password ) && 'roelmagdaleno' === $verification_code ) { $sql = 'My SQL Query'; // More code here... } else { echo 'Ups! Your verification code is wrong!'; }
Bueno, el código representa un inicio de sesión, pero volvemos a lo mismo: legibilidad y complejidad. Y todos hemos escrito código parecido al anterior, no me dejarán mentir.
¿Cómo podemos evitar el
else
? Aquí tenemos dos soluciones:Usar funciones para validar los datos y cláusulas de guardia; por lo tanto, el código anterior quedaría de la siguiente manera:
<?php $username = $_POST['username']; $password = $_POST['password']; if ( empty( $username ) || empty( $password ) ) { return 'user-login.php'; } if( ! validate_password_and_user_data( $username, $password, $verification_code ) ) { return 'Something is wrong with your data.'; } return 'All good! Go to dashboard.'; function validate_password_and_user_data( $username, $password, $verification_code ) { if( 'roelmagdaleno' !== $verification_code ) { return false; } $sql = 'My SQL query to get username data.'; if( $password !== $sql['password'] ) { return false; } return true; }
¿Es más código? Sí, pero ésta solución hace que nuestros ojos no sangren al momento de ver el código, y no, no hemos usado ni un
else
.El operador ternario
Vamos a usar un código directo, ¿has escrito un código como el siguiente?
<?php $new_color = ''; if( isset( $_POST['color'] ) ) { $new_color = $_POST['color']; } else { $new_color = 'red'; } echo 'The current color is ' . $new_color;
Lo que estamos haciendo en el código anterior es que si existe el valor de un color que es traído desde un formulario, lo asigne a la variable
$new_color
, pero, sino existe, asigna un color por default.El operador ternario puede reducir este tipo de condiciones con la siguiente sintaxis:
condición ? valor_si_es_verdadero : valor_si_es_falso;
Siguiendo la sintaxis anterior, nuestro código ahora sería:
<?php $new_color = isset( $_POST['color'] ) ? $_POST['color'] : 'red'; echo 'The current color is ' . $new_color;
¡Wow! Nos ahorramos 5 líneas de código.
Una buena práctica que siempre hago es hacer primero la condición sin el operador ternario, y después, ya que he analizado bien mi condición, aplico el operador ternario.
Si usas otro lenguaje de programación, busca en este enlace si es compatible, o puedes probar directo en tu código.
Operador de fusión de null
Y hay una característica mucho mejor, pero solo es a partir de PHP 7, y se llama: operador de fusión de null. Su sintaxis es:
variable_a_verificar_si_existe ?? valor_por_default;
Y nos sirve para verificar si una variable existe, y si existe y no es
null
, asigna ese valor a la variable, en caso contrario, asignará el valor por default. Por ejemplo:<?php $username = $_GET['username'] ?? 'John Doe';
Si
$_GET['username']
existe y no esnull
, entonces la variable$username
será igual a$_GET['username']
, en caso contrario, será igual a John Doe.Realmente, este operador hace una operación ternaria por detrás. El código anterior equivale a esta operación ternaria:
<?php $username = isset( $_GET['username'] ) ? $_GET['username'] : 'John Doe';
Recuerda, sólo funciona a partir de PHP 7 para arriba.
Condiciones Yoda
No explicaré aquí lo que es una condición Yoda, ya que he escrito un post específico para ese tema, y lo puedes leer en éste enlace.
Aplica los conocimientos aprendidos
Me da mucho gusto que hayas llegado hasta aquí, y espero que hayas aprendido algo, pero si te ha quedado alguna duda, tienes algún comentario ó sientes que me faltó una buena práctica, me gustaría que la compartieras en la caja de comentarios.
También te invito a compartir esta guía de buenas prácticas para que más desarrolladores nuevos aprendan a desarrollar de manera legible y menos compleja.
Y doy el agradecimiento a Carl Alexander por hacer su post del cual me he inspirado para escribir este.
¿Cómo actualizar PHP en macOS Sierra?
La librería usada en este post ya no recibe actualizaciones y recomiendan utilizar Homebrew para macOS donde podrás usar PHP hasta su versión más reciente.
Estaba programando unos scripts que requerían PHP 7, y trataba de ejecutarlos desde la terminal; por desgracia, me daban error y tardé como 3 o 5 minutos en saber que mi macOS Sierra, venía con PHP 5.6 por default. Por suerte, hay plugins que te permiten actualizar PHP en macOS Sierra de una forma muy fácil.
Actualizar PHP en macOS Sierra
Existe una página web llamada php-osx.liip.ch que nos brinda un paquete que contiene PHP 7 (u otras versiones), y que podremos instalarlo desde un sólo comando en nuestra Mac (OS X / macOS 10.6 – 10.12).
Paso I.
curl -s https://php-osx.liip.ch/install.sh | bash -s 7.3
Copia el comando anterior, y pégalo en tu terminal; pero antes, ¿notas que dice 7.3? Ahi tú puedes borrar el 7.3 y ponerle una de las siguientes versiones: 7.1, 7.0, 5.6, 5.5, 5.4 ó 5.3.
Después de que hayas escogido la versión a instalar, ejecutas el comando y empezará a instalar la versión de PHP que seleccionaste, no sin antes pedirte la contraseña para continuar.
Paso II.
Una vez instalado, puedes verificar la versión instalada desde tu terminal con el siguiente comando:
php --version
Podría suceder de que tu terminal muestre que tienes la versión 5.6.30, la que viene por defecto:
PHP 5.6.30 (cli) (built: Feb 7 2017 16:18:37) Copyright (c) 1997-2016 The PHP Group Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
Si esto ocurre, sólo tienes que ejecutar este comando:
export PATH=/usr/local/php5/bin:$PATH
Revisa de nuevo la versión, y ahora tiene que salir correctamente:
PHP 7.3.0 (cli) (built: May 6 2017 10:02:00) ( NTS ) Copyright (c) 1997-2017 The PHP Group Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
Resultados
Lo anterior debería funcionar, al menos funcionó para mí. La verdad es que solamente ocupo PHP desde la terminal para ejecutar scripts básicos, probar funciones, entre otros; de ahi en fuera utilizo un entorno de desarrollo llamado Local by Flywheel.
Espero que no tengas errores al tratar de instalar una nueva versión de PHP, pero si la tienes, no dudes en preguntar en los comentarios y con gusto te ayudaré a solucionarlo. 🙂
Changelog
09/02/2021. Se cambió la versión 7.1, usada en el post, a la última versión aceptada por la librería, 7.3. Y se agregó una advertencia al principio para usar Homebrew en vez de la librería presentada en este post.