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:
composer lint

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:

Comparte en redes o resume con la IA

Deja un comentario

ÚLTIMOS ARTÍCULOS

Cierre Ventana

Preview de plugins en WordPress Playground directamente desde el Pull Request

Cuando alguien abre un PR en un plugin de WordPress, el proceso habitual para revisarlo implica descargar la…

Cierre Ventana

3 años en el Plugins Team de WordPress.org

Ayer, 5 de mayo de 2026, cumplo 3 años como parte del Plugins Team de WordPress.org. Y este…

Cierre Ventana

De WordCamp a la meta: un fin de semana entre comunidad y carrera

¡Vaya fin de semana movido! Entre WordCamp Málaga y la Media Maratón de Granada, el fin de semana…