Analiza tu código automáticamente con PHPSTAN

En proyectos de WordPress, mantener un código limpio y libre de errores es fundamental para garantizar la calidad, la seguridad y la escalabilidad. Herramientas como PHPStan (análisis estático) y PHPLint (validación de sintaxis) se integran fácilmente en tus procesos de testing automatizado, ayudándote a detectar problemas antes de que lleguen a producción.

En esta entrada aprenderás cómo añadir ambas herramientas en tu flujo de tests para WordPress paso a paso.


¿Por qué usar PHPStan?

  • PHPStan: analiza tu código sin ejecutarlo, detectando errores de tipos, llamadas a métodos inexistentes y malas prácticas.
  • Ambas herramientas mejoran la calidad del código y facilitan la colaboración en equipos de desarrollo WordPress.

Instalación con Composer

Asegúrate de tener instalado Composer en tu entorno de desarrollo. Luego añade las dependencias:

composer require --dev phpstan/phpstan wp-coding-standards/wpcs szepeviktor/phpstan-wordpress phpstan/extension-installer

Esto instalará ambas herramientas dentro de tu carpeta vendor/.


Configuración de PHPStan

  1. Crea el archivo phpstan.neon.dist en la raíz del proyecto (incluye WooCommerce):
parameters:
    level: 1
    paths:
        - includes
    bootstrapFiles:
        - tests/phpstan-bootstrap.php
    excludePaths:
        - vendor/
        - node_modules (?)

Ejemplo phpstan

<?php
/**
 * PHPStan Bootstrap File
 * 
 * This file defines constants and functions that PHPStan needs to understand
 * but are not available during static analysis.
 */

// Define plugin constants that are used throughout the codebase
if (!defined('CONHOLD_PLUGIN_URL')) {
    define('CONHOLD_PLUGIN_URL', 'http://localhost/wp-content/plugins/connect-ecommerce/');
}

if (!defined('CONHOLD_VERSION')) {
    define('CONHOLD_VERSION', '1.0.0');
}

if (!defined('CONHOLD_FILE')) {
    define('CONHOLD_FILE', __FILE__);
}

// Define WordPress constants that might be missing
if (!defined('DOING_AJAX')) {
    define('DOING_AJAX', false);
}

if (!defined('WP_DEBUG')) {
    define('WP_DEBUG', false);
}

if (!defined('ABSPATH')) {
    define('ABSPATH', '/path/to/wordpress/');
}

// Mock WordPress functions that PHPStan can't find
if (!function_exists('wp_doing_ajax')) {
    function wp_doing_ajax() {
        return defined('DOING_AJAX') && DOING_AJAX;
    }
}

if (!function_exists('CONHOLD_get_options')) {
    function CONHOLD_get_options() {
        return [];
    }
}


// Mock Action Scheduler function
if (!function_exists('as_schedule_recurring_action')) {
    function as_schedule_recurring_action($timestamp, $interval_in_seconds, $hook, $args = [], $group = '') {
        return true;
    }
}

// Mock WP_CLI class
if (!class_exists('WP_CLI')) {
	class WP_CLI {
			public static function line($message) {
					echo $message . "\n";
			}
			public static function add_command($command, $class) {
					return true;
			}
	}
}

Configura composer.json:

"scripts": {
	"format": "phpcbf --standard=phpcs.xml.dist",
	"lint": "phpcs --standard=phpcs.xml.dist",
	"phpstan": "phpstan analyse --memory-limit=2048M"
}
  1. Ejecuta el análisis:
composer phpstan

Configuración con WooCommerce

composer require --dev php-stubs/wordpress-stubs php-stubs/woocommerce-stubs

Y añadir el include en el archivo de configuración

parameters:
    bootstrapFiles:
        - vendor/php-stubs/wordpress-stubs/wordpress-stubs.php
        - vendor/php-stubs/woocommerce-stubs/woocommerce-stubs.php
        #- vendor/php-stubs/woocommerce-stubs/woocommerce-packages-stubs.php

Configuración de PHPLint

  1. Crea un archivo .phplint.yml:
path: .
jobs: 10
extensions:
  - php
  1. Ejecuta el análisis:
vendor/bin/phplint

Integración con PHPUnit y GitHub Actions

Puedes añadir ambos chequeos en tus pipelines de CI/CD para que cada commit o pull request pase por estas validaciones.

Y añadir el archivo con tus propias reglas de Coding Standards:

<?xml version="1.0"?>
<ruleset name="Coding Standards for Internal Scanner Tool">
	<description>Description of Plugin.</description>

	<exclude-pattern>*/vendor/*</exclude-pattern>
	<exclude-pattern>reports/*</exclude-pattern>
	<exclude-pattern>php/tests/*</exclude-pattern>
	<exclude-pattern>php/prt_phpunit/*</exclude-pattern>

	<arg value="ps"/>
	<arg name="extensions" value="php"/>

	<file>./plugin.php</file>
	<file>./includes</file>
	<file>./templates</file>

	<rule ref="WordPress">
		<exclude name="Universal.Arrays.DisallowShortArraySyntax"/>
		<exclude name="WordPress.DB" />
		<exclude name="WordPress.Files.FileName"/>
		<exclude name="WordPress.NamingConventions.ValidFunctionName" />
	</rule>

	<rule ref="WordPress.WP.I18n">
		<properties>
			<property name="text_domain" type="array" value="plugin-name" />
		</properties>
	</rule>

	<rule ref="WordPress.Utils.I18nTextDomainFixer">
		<properties>
			<property name="old_text_domain" type="array">
				<element value="" />
			</property>
			<property name="new_text_domain" value="plugin-name" />
		</properties>
	</rule>
</ruleset>

De este modo, al ejecutar composer format o composer lint, se correrán PHPUnit, PHPStan y PHPLint juntos.

Añadir en .github/workflows/php-lint.yml

name: PHP Code Linting

on:
  push:
    branches:
      - trunk
      - 'release/**'
    # Only run if PHP-related files changed.
    paths:
      - '.github/workflows/php-lint.yml'
      - '**.php'
      - 'phpcs.xml.dist'
      - 'composer.json'
      - 'composer.lock'
  pull_request:
    branches:
      - trunk
      - 'release/**'
      - 'feature/**'
    # Only run if PHP-related files changed.
    paths:
      - '.github/workflows/php-lint.yml'
      - '**.php'
      - 'phpcs.xml.dist'
      - 'composer.json'
      - 'composer.lock'
    types:
      - opened
      - reopened
      - synchronize

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ github.ref != 'refs/heads/trunk' }}
jobs:
  php-lint:
    name: PHP
    runs-on: ubuntu-latest
    timeout-minutes: 20
    steps:
      - uses: actions/checkout@v4

      - uses: shivammathur/setup-php@v2
        with:
          php-version: '8.0'

      - name: Validate Composer configuration
        run: composer validate

      - name: Install PHP dependencies
        uses: ramsey/composer-install@a2636af0004d1c0499ffca16ac0b4cc94df70565
        with:
          composer-options: '--prefer-dist'

      - name: PHP Lint
        run: composer lint

      - name: PHP PHPStan
        run: composer phpstan

Conclusión

Integrar PHPStan y PHPLint en tus TESTs de WordPress es una manera sencilla de elevar la calidad del desarrollo, detectar errores de forma temprana y mejorar la robustez de tus plugins y temas.

Si quieres llevar tu proyecto al siguiente nivel, empieza por añadir estas herramientas en tu flujo de trabajo. 🚀👉 ¿Quieres que te prepare este artículo en formato markdown completo y listo para publicar en WordPress (con encabezados h2, h3, bloques de código y enlaces a las herramientas), o prefieres que lo deje en texto plano para que lo adaptes tú?

Referencias:

Deja un comentario

ÚLTIMOS ARTÍCULOS

Cierre Ventana

Analiza tu código automáticamente con PHPSTAN

En proyectos de WordPress, mantener un código limpio y libre de errores es fundamental para garantizar la calidad,…

Cierre Ventana

Desarrolla y crea Test para que tus plugins no tengan errores

Este es el tutorial que vamos a tener en cuenta para la charla de la WordCamp Galicia 2025.…

Cierre Ventana

A great year on the WordPress plugin team

It’s been a great year for the WordPress Plugins Team. You can see the numbers in a summary…

Este sitio está registrado en wpml.org como sitio de desarrollo. Cambia a una clave de sitio de producción en remove this banner.